struct类型,值传递的
-
声明
struct { name string age int } //几种声明使用方式: var P person // P现在就是person类型的变量了 P.name = "Astaxie" // 赋值"Astaxie"给P的name属性. P.age = 25 // 赋值"25"给变量P的age属性 //按照顺序提供初始化值 P := person{"Tom", 25} //通过field:value的方式初始化,这样可以任意顺序 P := person{age:24, name:"Tom"} //当然也可以通过new函数分配一个指针,此处P的类型为*person P := new(person)
struct的匿名字段
-
struct定义的时候是字段名与其类型一一对应,实际上Go支持只提供类型,而不写字段名的方式,也就是匿名字段,也称为嵌入字段。当匿名字段是一个struct的时候,那么这个struct所拥有的全部字段都被隐式地引入了当前定义的这个struct。
-
所有的内置类型和自定义类型都是可以作为匿名字段的
type Human struct { age int phone string // Human类型拥有的字段 } type Student struct { Human // 匿名字段,struct int // 内置类型作为匿名字段 phone string // 学生的phone字段 } //Student访问属性age的时候,就像访问自己所有用的字段一样 //匿名字段能够实现字段的继承。 // 初始化学生Jane jane := Student{Human:Human{35, "777-444-XXXX"},phone:"666-444-XXXX"} // 修改匿名内置类型字段 jane.int = 3 //最外层的优先访问 //访问student里面的phone字段 fmt.Println(jane.phone) // 如果我们要访问Human的phone字段 fmt.Println(jane.Human.phone)
interface
-
定义interface
type interfaceName interface { func1() func2() ...... }
-
interface类型定义了一组方法,如果某个对象实现了某个接口的所有方法,则此对象就实现了此接口。因此任意的类型都实现了空interface。
-
如果我们定义了一个interface的变量,那么这个变量里面可以存实现这个interface的任意类型的对象。所以空interface可以存储任意类型的数值。
-
一个函数把interface{}作为参数,那么他可以接受任意类型的值作为参数,如果一个函数返回interface{},那么也就可以返回任意类型的值。
-
嵌入interface如果一个interface1作为interface2的一个嵌入字段,那么interface2隐式的包含了interface1里面的method。
面向对象
method
-
method是附属在一个给定的类型上的,他的语法和函数的声明语法几乎一样,只是在func后面增加了一个receiver(也就是method所依从的主体)。语法如下:
func (**r ReceiverType)** funcName(parameters) (results)
-
虽然method的名字一模一样,但是如果接收者不一样,那么method就不一样
-
Receiver可以是值和指针, 两者的差别在于, 指针作为Receiver会对实例对象的内容发生操作,而普通类型作为Receiver并不对原实例对象发生操作。
-
method能作用在任何你自定义的类型、内置类型、struct等各种类型上面。
指针作为receiver
-
如果一个method的receiver是*T,你可以在一个T类型的实例变量V上面调用这个method,而不需要&V去调用这个method
-
如果一个method的receiver是T,你可以在一个*T类型的变量P上面调用这个method,而不需要 *P去调用这个method
func (b *Box) SetColor(c Color) { b.color = c } //*b.Color=c和b.Color=c这两种方式都是正确的 //当你用指针去访问相应的字段时(虽然指针没有任何的字段) //Go知道你要通过指针去获取这个值。 func (bl BoxList) PaintItBlack() { for i := range bl { bl[i].SetColor(BLACK) } } //PaintItBlack里面调用SetColor的时候写成 //(&bl[i]).SetColor(BLACK)和bl[i].SetColor(BLACK)都可以 //因为SetColor的receiver是*Box都可以,因为Go知道receiver是指针,他自动帮你转了。
method继承
-
如果匿名字段实现了一个method,那么包含这个匿名字段的struct也能调用该method。让我们来看下面这个例子
type Human struct { name string age int phone string } type Student struct { Human //匿名字段 school string } type Employee struct { Human //匿名字段 company string } //在human上面定义了一个method func (h *Human) SayHi() {a fmt.Printf("Hi, I am %s you can call me on %s ", h.name, h.phone) } func main() { mark := Student{Human{"Mark", 25, "222-222-YYYY"}, "MIT"} sam := Employee{Human{"Sam", 45, "111-888-XXXX"}, "Golang Inc"} mark.SayHi() sam.SayHi() }
method重写
//如果Employee想要实现自己的SayHi
//我们可以在Employee上面定义一个method,重写了匿名字段的方法。
func (e *Employee) SayHi() {
fmt.Printf("Hi, I am %s, I work at %s. Call me on %s
", e.name,e.company, e.phone)
}
参考书籍:
https://github.com/astaxie/build-web-application-with-golang/blob/master/zh/preface.md