结构和方法 结构体工厂 Go 中不支持向面向对象语言的方法那样构造类的子方法,但是可以根据构造子工厂的方法来实现子方法。一般来说,工厂的名字用 New 开头。
1 2 3 4 5 6 7 8 9 10 11 type File struct { fd int name string } func NewFile (fd int , name string ) *File { if fd < 0 { return nil } return &File{fd, name} }
如果结构体的命名开头是小写的话,可以强制要求使用结构体工厂。
匿名字段和内嵌结构体 结构体可以包含一个或多个 匿名(或内嵌)字段 ,即这些字段没有显式的名字,只有字段的类型是必须的,此时类型就是字段的名字。匿名字段本身可以是一个结构体类型,即 结构体可以包含内嵌结构体 。
可以粗略地将这个和面向对象语言中的 继承 概念相比较,随后将会看到它被用来模拟类似继承的行为。Go 语言中的继承是通过内嵌或组合来实现的,所以可以说,在 Go 语言中,相比较于继承,组合更受青睐。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 type A struct { ax, ay int x int y int } type B struct { A bx, by float32 x int y string } func main () { b := B{A{1 , 2 , 3 , 4 }, 5.0 , 6.0 , 7 , "8" } fmt.Println(b.ax, b.ay, b.bx, b.by) fmt.Println(b.A) fmt.Println(b.x) }
方法 方法类似于面向对象语言中的 成员函数 ,不过 Go 虽然不会有一个 class 的概念,但是可以用以下的方法达到类似的效果。
1 2 3 func (recv receiver_type) methodName(parameter_list) (return_value_list) { }
其中 recv 就类似与面向对象语言中的 self 或者 this。
需要注意的点:
类型和作用在它上面定义的方法必须在同一个包里定义,这就是为什么不能在 int、float 或类似这些的类型上定义方法。
1 2 3 4 5 6 7 8 package mainimport "container/list" func (p *list.List) Iter() { }
但是有一个间接的方式:可以先定义该类型(比如:int 或 float)的别名类型,然后再为别名类型定义方法。或者像下面这样将它作为匿名类型嵌入在一个新的结构体中。当然方法只在这个别名类型上有效。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 package mainimport ( "fmt" "time" ) type myTime struct { time.Time } func (t myTime) first3Chars() string { return t.Time.String()[0 :3 ] }
内嵌类型的方法和继承
在类型中嵌入功能
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 package mainimport ( "fmt" ) type Log struct { msg string } type Customer struct { Name string log *Log } func main () { c := new (Customer) c.Name = "Barak Obama" c.log = new (Log) c.log.msg = "1 - Yes we can!" c = &Customer{"Barak Obama" , &Log{"1 - Yes we can!" }} c.Log().Add("2 - After me the world will be a better place!" ) fmt.Println(c.Log()) } func (l *Log) Add(s string ) { l.msg += "\n" + s } func (l *Log) String() string { return l.msg } func (c *Customer) Log() *Log { return c.log }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 package mainimport ( "fmt" ) type Log struct { msg string } type Customer struct { Name string Log } func main () { c := &Customer{"Barak Obama" , Log{"1 - Yes we can!" }} c.Add("2 - After me the world will be a better place!" ) fmt.Println(c) } func (l *Log) Add(s string ) { l.msg += "\n" + s } func (l *Log) String() string { return l.msg } func (c *Customer) String() string { return c.Name + "\nLog:" + fmt.Sprintln(c.Log) }
多重继承 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 package mainimport ( "fmt" ) type Camera struct {}func (c *Camera) TakeAPicture() string { return "Click" } type Phone struct {}func (p *Phone) Call() string { return "Ring Ring" } type CameraPhone struct { Camera Phone } func main () { cp := new (CameraPhone) fmt.Println("Our new CameraPhone exhibits multiple behaviors..." ) fmt.Println("It exhibits behavior of a Camera: " , cp.TakeAPicture()) fmt.Println("It works like a Phone too: " , cp.Call()) }