定义
type Person struct {Name stringAge uint8}func main() {方式一var p1 Personp1.Name="jack"p1.Age=19fmt.Println(p1)//{jack 19}方式二//var p2 Person =Person{"tom",20}与下面等价var p2 Person =Person{}p2.Name="tom"p2.Age=20fmt.Println(p2)//{tom 20}方式三var p3 *Person = new(Person) //注意通过new方式创建的实例,类型是一个指针(*p3).Name="mary"//标准方式,为什么不能*p3.Name,因为.的优先级比*高p3.Age=21//简化方式fmt.Println(*p3)//{mary 21}方式四//var p4 *Person = &Person{"Allen",22}与下面等价var p4 *Person = &Person{}(*p4).Name="Allen"//标准方式p4.Age=22//简化方式fmt.Println(*p4)//{Allen 22}方式五var p4 *Person = &Person{Name:"Allen"} //指定名称初始化,不需要将全部参数赋值}
细节
实例里的属性的地址是连续分布的
type Human struct {Name int64Age int64Sex int64}func main() {h1 :=Human{}h1.Name=11h1.Age=11h1.Sex=11fmt.Printf("h1%p\n",&h1)fmt.Printf("h1.Name%p\th1.Age:%p\th1.Sex:%p",&h1.Name,&h1.Age,&h1.Sex)//h1.Name0xc000010380 h1.Age:0xc000010388 h1.Sex:0xc000010390//h1实例里的属性的地址是连续分布的//并且同数组,切片,map等一样,本身的地址与第一个元素的地址相同}
_
tag标签
type Human1 struct {Name stringAge int64Sex string}type Human2 struct {Name string `json:"name"`Age int64 `json:"age"`Sex string `json:"sex"`}func main() {h1 :=Human1{"tom",10,"男"}h2 :=Human2{"mary",20,"女"}h1str,_ := json.Marshal(h1)h2str,_ := json.Marshal(h2)fmt.Println(string(h1str))//{"Name":"tom","Age":10,"Sex":"男"}fmt.Println(string(h2str))//{"name":"mary","age":20,"sex":"女"}}
结构体支持匿名字段与基本类型的匿名字段
type A struct {intn int}func main() {a :=A{1,2}fmt.Println(a.int,a.n)}
面对对象的思想
工厂模式
utlis包
type student struct {Name stringage int8}//由于student的首字母是小写的,因此在别的pck中是不能使用的func GetStudent(name string,age int8) *student{return &student{Name:name,age:age,}}//由于student中age字段是首字母是小写的,因此该字段在别的包是访问不到的func (s *student) GetAge() int8{return s.age}
main包
func main() {s :=utlis.GetStudent("张三",18)fmt.Println("姓名=",s.Name,"年龄=",s.GetAge())}
继承
type Animal struct {Name stringAge int8}func (A *Animal) Eat(){fmt.Println(A.Name,"要吃东西")}func (A *Animal) Drink(){fmt.Println("喝水")}type Dog struct {Animal//实现继承Name string //重写属性}func (D *Dog) Eat(){ //重写方法fmt.Println(D.Name,"吃骨头")}func main() {//var d Dog=Dog{Animal{"旺财一号",3},"旺财二号"}//可以这样定义var d Dog//如果d.Animal.Name="旺财",Animal中Eat()方法中A.Name才拿到值//但是由于Dog重写了Name属性,设置d.Animal.Name="旺财",Dog中的Eat()方法中D.Name拿不到值d.Name="旺财"d.Age = 8 //由于dog是继承于animal的,d.Animal.Age = 8相关等价d.Eat()//狗吃骨头d.Animal.Eat()//''要吃东西,}
注意事项
- 父类的私有属性与方法可以被子类继承
有名结构体在指定属性与方法时要带上名字
type Animal struct {Name stringAge int8}type Dog struct {A Animal//有名结构体}func main() {var d Dog//d.Name = "旺财",语法不通过d.A.Name = "旺财"}
结构体嵌套多个匿名结构体,且结构体有相同的属性与方法(同时结构体本身没有定义相同的属性与方法),那么在访问时,需要指定匿名结构体的名字
type A struct {Name stringAge int8}type B struct {Name stringAge int8Sex string}type C struct {AB}func main() {var c C//c.Name="旺财" //语法不通过,A与B中都有Name属性c.A.Name="旺财"c.Sex="男" //只有B中有Sex属性,所以可以这样使用}
组合嵌套的其他定义方式
type A struct {Name stringAge int8}type B struct {Sex string}type C struct {AB}type D struct {*A*B}func main() {方式一:var c C=C{A{"旺财一号",3},B{"男"}}方式二:var c2 C=C{A{Name:"旺财二号",Age:3,},B{Sex:"男",},}指针型方式一:d :=D{&A{"旺财三号",3},&B{"男"}}指针型方式二:类似普通型方式二fmt.Println(*d.A,*d.B)//注意这里不能用(*d).A,d不是指针,d.A才是指针}
结构体内字段分布具有连续性
1.结构体内无引用类型
type Person struct {Name stringAge int8Addr string}func main() {p := &Person{Name:"aaa",Age:20,Addr:"***",}fmt.Printf("p变量地址:%p\n", &p) // 0xc000098018fmt.Printf("Person地址:%p\n", p) // 0xc000074330fmt.Printf("Name地址:%p\n", &p.Name) // 0xc000074330fmt.Printf("Age地址:%p\n", &p.Age) // 0xc000074340fmt.Printf("Addr地址:%p\n", &p.Addr) // 0xc000074348}
内存分布图
2.结构体内有引用类型
还是具有连续性的特征
type Person struct {Cars []stringName stringAge int8Addr string}func main() {p := &Person{Cars:[]string{"audi","buick"},Name:"aaa",Age:20,Addr:"***",}fmt.Printf("p变量地址:%p\n", &p) // 0xc000098018fmt.Printf("Person地址:%p\n", p) // 0xc00001a0c0fmt.Printf("Cars地址:%p\n", &p.Cars) // 0xc00001a0c0fmt.Printf("Name地址:%p\n", &p.Name) // 0xc00001a0d8fmt.Printf("Age地址:%p\n", &p.Age) // 0xc00001a0e8fmt.Printf("Addr地址:%p\n", &p.Addr) // 0xc00001a0f0}
3.%v与%p的理解
type InfoS struct {Addr string}type Person1 struct {Info *InfoS}func main() {p := &Person1{new(InfoS)}fmt.Printf("%p\n", &p) // 0xc000006028fmt.Printf("%p\n", p) // 0xc000006030fmt.Printf("%p\n", p.Info) // 0xc00003a1f0fmt.Printf("%p\n", &p.Info) // 0xc000006030fmt.Printf("%v\n", p) // &{0xc00003a1f0}// p存的是指针,用%v时,如果是指针类型,会默认对指针做一次取值操作,注意是一次}

其他
类型为func
type Myfunc func(i, n int64) boolfunc (m Myfunc) run1(i, n int64) bool {return m(1, 2)}func (m Myfunc) run2(i, n int64) bool {return i > n}func main() {f := Myfunc(func(i, n int64) bool {return i < n})fmt.Println(f.run1(1, 2), f.run2(1, 2)) //true false}
