Go:struct

一、使用方式

方式3和方式4返回的是:结构体指针,编译器底层对 p.Name 做了转化 *(p).Name,方便程序员使用。

type Person struct {
	Name string
	Age int
}

func main() {
	// 方式1
	var p Person
	fmt.Println(p)  // { 0}
	var p1 = Person{}
	p1.Name = "a"
	p1.Age = 1
	fmt.Println(p1) // {a 1}

	// 方式2
	var p2 = Person{"b", 2}
	var p3 = Person{
		Name: "b",
		Age: 2,
	}
	p4 := Person{"b", 2}
	p5 := Person{
		Name: "b",
		Age: 2,
	}
	fmt.Println(p2, p3, p4, p5) // {b 2} {b 2} {b 2} {b 2}

	// 方式3
	var p6 = new(Person) // var p6 *Person = new(Person)
	/*
	go的设计者,为了程序员的使用方便,底层会对 p6.Name = "c"进行处理,
	相当于*(p6).Name = "c"
	*/
	p6.Name = "c"	 // *(p6).Name = "c"
	p6.Age = 3   	 // *(p6).Age = 3
	fmt.Println(p6)  // &{c 3}
	fmt.Println(*p6) // {c 3}

	// 方式4(同方式3)
	var p7 = &Person{}
	p7.Name = "d"
	p7.Age = 4
	fmt.Println(p7, *p7)   // &{d 4} {d 4}

	var p8 = &Person{"e", 5}
	fmt.Println(p8, *p8)   // &{e 5} {e 5}

	p9 := &Person{}
	p9.Name = "f"
	p9.Age = 6
	fmt.Println(p9, *p9)   // &{f 6} {f 6}

	p10 := &Person{"g", 7}
	fmt.Println(p10, *p10) // &{g 7} {g 7}
}

二、结构体中的指针、slice、map的默认值都是nil,即还没分配空间

type Person struct {
	Name string
	Age int
	Score [3]float64
	ptr *int
	s []int
	m map[string]string
}

func main() {
	var p Person
	fmt.Println(p) // { 0 [0 0 0] <nil> [] map[]}
	if p.ptr == nil {
		fmt.Println("true") // true
	}
	if p.s == nil {
		fmt.Println("true") // true
	}
	if p.m == nil {
		fmt.Println("true") // true
	}
	// 使用slice和map时,一定要make!!!
	p.s = make([]int, 2)
	p.s[0] = 88
	fmt.Println(p.s) // [88 0]
	p.m = make(map[string]string, 2)
	p.m["key"] = "value"
	fmt.Println(p.m) // map[key:value]
}

三、结构体的tag

struct的每个字段上,可以写上一个tag,该tag可以通过反射机制获取,常见的使用场景就是序列化和反序列化。

package main

import (
	"encoding/json"
	"fmt"
)

type Person struct{
	Name string `json:"name"` // `json:"name"`就是结构体tag
	Age int // `json:"age"` ,没有写tag,序列化后则为大写字母,如果字段为小写,其他包又不可见
}

func main() {
	person := Person{"佩奇", 18}
	jsonStr, err := json.Marshal(person)
	if err != nil {
		fmt.Println(err)
	} else {
		fmt.Println(string(jsonStr)) // {"name":"佩奇","Age":18}
	}
}

四、其他

结构体的所有字段在内存中是连续的。

type Student struct {
	A int
	B int
	C int
}

func main() {
	s := Student{1, 20, 300}
	fmt.Println(&s.A) // 0xc00000e3a0
	fmt.Println(&s.B) // 0xc00000e3a8
	fmt.Println(&s.C) // 0xc00000e3b0
}

结构体是用户单独定义的类型,和其他类型进行转换时需要有完全相同的字段(名字、个数、类型)。

type A struct {
	Name string
}

type B struct {
	Name string
}

type C A // 结构体进行type重新定义(相当于取别名)

func main() {
	var a A
	var b B
	a = A(b) // 可以强转,但有前提
	var c C
	c = C(a) // 可以强转
	fmt.Println(a, b, c)
}

 

posted @ 2019-05-27 13:33  就俗人一个  阅读(278)  评论(0编辑  收藏  举报