Bootstrap

Go 结构体(struct)

go语言中的结构体:

Go 结构体与初始化 - Helldorado - 博客园Go 通过类型别名(alias types)和结构体的形式支持用户自定义类型。 结构体是复合类型,当需要定义类型,它由一系列属性组成,每个属性都有自己的类型和值的时候,就应该使用结构体,它把数据聚集在https://www.cnblogs.com/liyutian/p/10050320.html

结构体是值传递类型:

go语言中类型分类

  • 值类型:int,float,bool,string,array,struct
  • 引用类型:slice,map,function,pointer
package main

import "fmt"

type Person struct {
    name string
    age int
}

func main() {
    p1 := Person{name:"zhangsan", age:30}
    fmt.Println(p1)  // {zhangsan 30}
    fmt.Printf("%p,%T\n", &p1,p1)  // 0x3842dd3, main.Person

    p2:=p1
    fmt.Println(p2)  // {zhangsan 30}
    fmt.Printf("%p,%T\n", &p2,p2)  // 0x38dfsd3, main.Person

    p2.name = "lisi"
    fmt.Println(p2)  // {lisi 30}
    fmt.Println(p1)  // {zhangsan 30}
}

结构体指针(浅拷贝):

package main

import "fmt"

type Person struct {
    name string
    age int
}

func main() {
    p1 := Person{name:"zhangsan", age:30}
    fmt.Println(p1)  // {zhangsan 30}
    fmt.Printf("%p,%T\n", &p1,p1)  // 0x3842dd3, main.Person

    // 定义结构体指针
    var p3 *Person
    p3 = &p1
    fmt.Println(p3)  // &{zhangsan 30}
    fmt.Printf("%p,%T\n", &p3,p3)  // 0x38ds4dd3, main.Person
    fmt.Println(*p3)  // {zhangsan 30}

    (*p3).name = "wangwu"
    // p3.name = "wangwu"  // 简写
    fmt.Println(*p3)  // {wangwu 30}
    fmt.Println(p1)  // {wangwu 30}
}

new函数与make函数:

  • new()用于各种类型的内存分配,new(T)分配了零值填充的T类型的内存空间,并返回其地址,即一个*T类型的值,它返回了一个指针,指向新分配的类型T的零值。
  • make(T,args)只能创建slice,map和channel,并且返回一个有初始值(非零)的T类型,而不是*T。对于slice,map和channel来说,make初始化了内部的数据结构,填充适当的值。
package main

import "fmt"

type Person struct {
    name string
    age int
}

func main() {
    p1 := Person{name:"zhangsan", age:30}
    fmt.Println(p1)  // {zhangsan 30}
    fmt.Printf("%p,%T\n", &p1,p1)  // 0x3842dd3, main.Person

    // new()函数
    p4 := new(Person)
    fmt.Printf("%p,%T\n", &p4,p4)  // 0x38d42d55d3, *main.Person
    fmt.Println(p4)  // { 0}
    
    // (*p4).name = "aaa"
    p4.name = "aaa"
    p4.age = 33
    fmt.Println(*p4)  // {aaa 33}
}

匿名结构体:

package main

import "fmt"

type Person struct {
    name string
    age int
}

func main() {
    s2 := struct {
        name string
        age int
    }{
        name: "zhangsan",
        age:23,
    }

    fmt.Println(s2)  // {zhangsan 23}
}

匿名结构体,提升字段:

当结构体中定义的字段为另一个结构体,且这个字段是匿名字段时,访问数据时可以省略匿名结构体名。相当于模拟其他语言中的继承关系

package main

import "fmt"

type Book struct {
    bookName string
    price float64
}

type Student struct {
    Book  // 匿名字段
    name string
    age int
}

func main() {
    s2 := Student{name:"zs", age:12, Book:Book{bookName:"语文",price:45.25}}

    fmt.Println(s2.name)  // zs
    fmt.Println(s2.age)  // 12
    
    /*
    Student结构体将Book结构体作为一个匿名字段,那么Book结构体中的字段对于Studen来将,就是提升字段
    则在Student对象可以直接访问Book中的字段
    */
    fmt.Println(s2.Book.bookName)  // 语文
    fmt.Println(s2.Book.price)  // 45.25
    // 简写(匿名字段结构体-->字段提升)
    fmt.Println(s2.bookName)  // 语文  
    fmt.Println(s2.price)  // 45.25  

}

结构体匿名字段:

package main

import "fmt"

type Person struct {
    string   // 匿名字段,匿名字段不能重复,否则报错
    int
}

func main() {
    s2 := Person{"aa", 12}
    
    // 匿名字段获取数据,将数据类型作为字段名
    fmt.Println(s2.string)  // aa
    fmt.Println(s2.int)  // 12
}

结构体嵌套:

因为结构体是值类型,为避免重复开辟内存空间,使用结构体嵌套时,尽量使用结构体指针

package main

import "fmt"

type Book struct {
    name string
    price float64
}

type Student1 struct {
    name string
    age int
    book Book  // 值传递,修改当前结构体数据,不影响原Book结构体数据
}

type Student2 struct {
    name string
    age int
    book *Book   // 指针传递,地址引用,修改结构体数据,则原Book结构体数据改变
}

func main() {
    book := Book{name:"语文", price:32.4}

    s1 := Student{name:"zhangsan", age:12,book=book}
    s2 := Student{name:"zhangsan", age:12,book=&book}  // 指针,节约内存,按应用场景而定怎么使用
}

指针与结构体应用:

package main

import (
	"fmt"
)

type Persion struct {
	Name string
	Age  int
}

func main() {
	vv := make([]string, 0)
	// kvs := make([]*Persion, 0)
	// p := &Persion{Name: "zhangs", Age: 4}
	// fmt.Println("p:>>>", p)
	// kvs = append(kvs, p)
	// p2 := &Persion{Name: "lisi", Age: 43}
	// kvs = append(kvs, p2)

	kvss := []*Persion{&Persion{Name: "zhangs", Age: 4}, &Persion{Name: "lisi", Age: 46}}

	for k, v := range kvss {
		fmt.Printf("%s -> %s\n", k, v)
		vv = append(vv, v.Name)
	}
	fmt.Println("aa:", vv)
}

悦读

道可道,非常道;名可名,非常名。 无名,天地之始,有名,万物之母。 故常无欲,以观其妙,常有欲,以观其徼。 此两者,同出而异名,同谓之玄,玄之又玄,众妙之门。

;