1. 函数一等公民

  • 函数可以返回多个值
  • 所有参数都值传递,与java相同
  • 函数可以作为变量的值,与java对比,lambda
  • 函数可以作为参数和返回值

    2. 可变参数

    语法 ops ... type

    3. defer

    延迟执行,类似于java的finally

    4. 练习代码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”) }

  1. <a name="jYPy1"></a>
  2. ## 5. 封装数据和行为>>对象
  3. 类型定义
  4. ```go
  5. type TypeName struct{
  6. Id string
  7. Name string
  8. Age int
  9. }

行为定义1

  1. func (t TypeName) String{
  2. fmt.Printf("Address is %x", unsafe.Pointer(&e.Name))
  3. return fmt.Sprintf("ID:%s/Name:%s/Age:%d", e.Id, e.Name, e.Age)
  4. }

行为定义2

  1. func (t *TypeName) String{
  2. fmt.Printf("Address is %x", unsafe.Pointer(&e.Name))
  3. return fmt.Sprintf("ID:%s/Name:%s/Age:%d", e.Id, e.Name, e.Age)
  4. }

两者的不同是,前者会进行内存赋值。

6. 接口

接口与实现没有绑定关系,实现仅需要实现与接口的方法签名完全相同的方法,就表示实现与接口的关系。

  1. type MyProgrammer interface {
  2. WriteHello() string
  3. }
  4. type MyGoProgrammer struct {
  5. }
  6. func (gop *MyGoProgrammer) WriteHello() string{
  7. return "fmt.Println(\"hello world!\")"
  8. }
  9. func TestClient1(t *testing.T){
  10. var p MyProgrammer
  11. p = new(MyGoProgrammer)
  12. t.Log(p.WriteHello())
  13. }

7. 自定义类型

  1. type aliasInt int

8. 不支持继承只支持复合

  1. type Pet struct {
  2. }
  3. func (p *Pet) Speak() {
  4. fmt.Print("...")
  5. }
  6. func (p *Pet) SpeakTo(host string) {
  7. p.Speak()
  8. fmt.Println(" ", host)
  9. }
  10. type Dog struct {
  11. //匿名属性
  12. Pet
  13. p *Pet
  14. }
  15. func (d *Dog) Speak() {
  16. // 复合调用
  17. fmt.Print(d.p.Speak())
  18. fmt.Print("Wang!")
  19. }
  20. func TestDog(t *testing.T) {
  21. dog := new(Dog)
  22. dog.SpeakTo("Chao")
  23. }

9. 空接口

空接口相当于java的Object类型,代指所有类型。

  1. // p 是一个空接口,表示任何类型
  2. p interface{}
  3. // 获取p的类型
  4. p.(type)
  5. func DoSomething(p interface{}) {
  6. // if i, ok := p.(int); ok {
  7. // fmt.Println("Integer", i)
  8. // return
  9. // }
  10. // if s, ok := p.(string); ok {
  11. // fmt.Println("stirng", s)
  12. // return
  13. // }
  14. // fmt.Println("Unknow Type")
  15. switch v := p.(type) {
  16. case int:
  17. fmt.Println("Integer", v)
  18. case string:
  19. fmt.Println("String", v)
  20. default:
  21. fmt.Println("Unknow Type")
  22. }
  23. }
  24. func TestEmptyInterfaceAssertion(t *testing.T) {
  25. DoSomething(10)
  26. DoSomething("10")
  27. }

10. Go接口最佳实践

  • 倾向于使用小的接口定义,Go语言很多接口都只包含一个方法
  • 较大的接口定义,可以由多个小接口定义组合而成

    1. type Reader interface {
    2. Read(p []byte) (n int, err error)
    3. }
    4. type Writer interface {
    5. Write(p []byte) (n int, err error)
    6. }
    7. type ReadWriter interface {
    8. Reader
    9. Writer
    10. }
  • 只依赖于必要功能的最小接口