1. 函数一等公民
- 函数可以返回多个值
- 所有参数都值传递,与java相同
- 函数可以作为变量的值,与java对比,lambda
- 函数可以作为参数和返回值
2. 可变参数
语法ops ... type3. defer
延迟执行,类似于java的finally4. 练习代码1
```bash package fn
import ( “fmt” “math/rand” “testing” “time” )
func returnMultiValues() (int, int) { return rand.Intn(10), rand.Intn(10) }
func TestReturnMultiValues(t *testing.T) { a, b := returnMultiValues() t.Log(a, b) }
func timeSpent(inner func(op string) int) func(op string) int { return func(str string) int { start := time.Now() ret := inner(str) fmt.Println(“time spent:”, time.Since(start).Seconds()) return ret } }
func slowFunc(str string) int { time.Sleep(time.Second * 1) return len(str) }
func TestTimeSpent(t *testing.T) { outer := timeSpent(slowFunc) t.Log(outer(“hello”)) }
func sum(ops …int) int { ret := 0 for _, op := range ops { ret += op } return ret }
func TestSum(t *testing.T) { t.Log(sum(1, 2, 3, 4), sum(2, 3, 4, 5, 6, 7)) }
func cleanResource(){ fmt.Println(“clean resources!”) }
func TestCleanResource(t *testing.T){ defer cleanResource() t.Log(“start”) panic(“发生了异常”) //t.Log(“end”) }
<a name="jYPy1"></a>## 5. 封装数据和行为>>对象类型定义```gotype TypeName struct{Id stringName stringAge int}
行为定义1
func (t TypeName) String{fmt.Printf("Address is %x", unsafe.Pointer(&e.Name))return fmt.Sprintf("ID:%s/Name:%s/Age:%d", e.Id, e.Name, e.Age)}
行为定义2
func (t *TypeName) String{fmt.Printf("Address is %x", unsafe.Pointer(&e.Name))return fmt.Sprintf("ID:%s/Name:%s/Age:%d", e.Id, e.Name, e.Age)}
6. 接口
接口与实现没有绑定关系,实现仅需要实现与接口的方法签名完全相同的方法,就表示实现与接口的关系。
type MyProgrammer interface {WriteHello() string}type MyGoProgrammer struct {}func (gop *MyGoProgrammer) WriteHello() string{return "fmt.Println(\"hello world!\")"}func TestClient1(t *testing.T){var p MyProgrammerp = new(MyGoProgrammer)t.Log(p.WriteHello())}
7. 自定义类型
type aliasInt int
8. 不支持继承只支持复合
type Pet struct {}func (p *Pet) Speak() {fmt.Print("...")}func (p *Pet) SpeakTo(host string) {p.Speak()fmt.Println(" ", host)}type Dog struct {//匿名属性Petp *Pet}func (d *Dog) Speak() {// 复合调用fmt.Print(d.p.Speak())fmt.Print("Wang!")}func TestDog(t *testing.T) {dog := new(Dog)dog.SpeakTo("Chao")}
9. 空接口
空接口相当于java的Object类型,代指所有类型。
// p 是一个空接口,表示任何类型p interface{}// 获取p的类型p.(type)func DoSomething(p interface{}) {// if i, ok := p.(int); ok {// fmt.Println("Integer", i)// return// }// if s, ok := p.(string); ok {// fmt.Println("stirng", s)// return// }// fmt.Println("Unknow Type")switch v := p.(type) {case int:fmt.Println("Integer", v)case string:fmt.Println("String", v)default:fmt.Println("Unknow Type")}}func TestEmptyInterfaceAssertion(t *testing.T) {DoSomething(10)DoSomething("10")}
10. Go接口最佳实践
- 倾向于使用小的接口定义,Go语言很多接口都只包含一个方法
较大的接口定义,可以由多个小接口定义组合而成
type Reader interface {Read(p []byte) (n int, err error)}type Writer interface {Write(p []byte) (n int, err error)}type ReadWriter interface {ReaderWriter}
只依赖于必要功能的最小接口
