Go 结构体使用注意事项和细节

结构体使用注意事项和细节

  • 结构体的所有字段在内存中是连续
//结构体
type Point struct {
	x int
	y int
}

//结构体
type Rect struct {
	leftUp, rightDown  Point
}

func main() {
	r1 := Rect{Point{1,2}, Point{3,4}}
    //r1有四个int, 在内存中是连续分布
    //打印地址
   fmt.Printf("r1.leftUp.x 地址=%p r1.leftUp.y 地址=%p r1.rightDown.x 地址=%p r1.rightDown.y 地址=%p \n",
    &r1.leftUp.x, &r1.leftUp.y, &r1.rightDown.x, &r1.rightDown.y)

}
  • 输出结果:
r1.leftUp.x 地址=0xc00009e120 r1.leftUp.y 地址=0xc00009e128 r1.rightDown.x 地址=0xc00009e130 r1.rightDown.y 地址=0xc00009e138
  • 内存示意图:


//结构体
type Point struct {
	x int
	y int
}

//结构体
type Rect2 struct {
	leftUp, rightDown  *Point
}

func main() {
	r2 := Rect2{&Point{10,20}, &Point{30,4}0}
    
    //打印地址
fmt.Printf("r2.leftUp 本身地址=%p r2.rightDown 本身地址=%p \n", 
	&r2.leftUp, &r2.rightDown)

//他们指向的地址不一定是连续..., 这个要看系统在运行时是如何分配
fmt.Printf("r2.leftUp 指向地址=%p r2.rightDown 指向地址=%p \n", 
	r2.leftUp, r2.rightDown)

}
  • 输出结果:
r2.leftUp 本身地址=0xc0000881e0 r2.rightDown 本身地址=0xc0000881e8
r2.leftUp 指向地址=0xc0000a0080 r2.rightDown 指向地址=0xc0000a0090
  • r2有两个 *Point类型,这个两个*Point类型的本身地址也是连续的,
  • 但是他们指向的地址不一定是连续

  • 结构体是用户单独定义的类型,和其它类型进行转换时需要有完全相同的字段(名字、个数和类型)
type A struct {
	Num int
}
type B struct {
	Num int
}

func main() {
	var a A
	var b B
	a = A(b) 
	fmt.Println(a, b)
}
  • a = A(b) ,可以转换,但是有要求,就是结构体的的字段要完全一样(包括:名字、个数和类型!)

  • 结构体进行 type 重新定义(相当于取别名)Golang 认为是新的数据类型,但是相互间可以强转

 

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


func Marshal

  • 参考文档链接: https://studygolang.com/pkgdoc
  • package json

  • import "encoding/json"
  • json包实现了json对象的编解码。Json对象和go类型的映射关系请参见Marshal和Unmarshal函数的文档。
func Marshal(v interface{}) ([]byte, error)
  • Marshal函数返回v的json编码。
  • Marshal函数会递归的处理值。如果一个值实现了Marshaler接口切非nil指针,会调用其MarshalJSON方法来生成json编码。nil指针异常并不是严格必需的,但会模拟与UnmarshalJSON的行为类似的必需的异常。
  • 否则,Marshal函数使用下面的基于类型的默认编码格式:
  • 布尔类型编码为json布尔类型。
  • 浮点数、整数和Number类型的值编码为json数字类型。
  • 字符串编码为json字符串。角括号"<"和">"会转义为"\u003c"和"\u003e"以避免某些浏览器吧json输出错误理解为HTML。基于同样的原因,"&"转义为"\u0026"。
  • 数组和切片类型的值编码为json数组,但[]byte编码为base64编码字符串,nil切片编码为null。
  • 结构体的值编码为json对象。每一个导出字段变成该对象的一个成员,除非:
- 字段的标签是"-"
- 字段是空值,而其标签指定了omitempty选项
  • 空值是false、0、""、nil指针、nil接口、长度为0的数组、切片、映射。对象默认键字符串是结构体的字段名,但可以在结构体字段的标签里指定。结构体标签值里的"json"键为键名,后跟可选的逗号和选项,举例如下:
// 字段被本包忽略
Field int `json:"-"`
// 字段在json里的键为"myName"
Field int `json:"myName"`
// 字段在json里的键为"myName"且如果字段为空值将在对象中省略掉
Field int `json:"myName,omitempty"`
// 字段在json里的键为"Field"(默认值),但如果字段为空值会跳过;注意前导的逗号
Field int `json:",omitempty"`
  • "string"选项标记一个字段在编码json时应编码为字符串。它只适用于字符串、浮点数、整数类型的字段。这个额外水平的编码选项有时候会用于和javascript程序交互:
Int64String int64 `json:",string"`

 

演示案例

type Monster struct{
	Name string `json:"name"` // `json:"name"` 就是 struct tag
	Age int `json:"age"`
	Skill string `json:"skill"`
}
func main() {
    //1. 创建一个Monster变量
    monster := Monster{"鲁班七号", 3, "鲨鱼炮"}
     //  将monster变量序列化为 json格式字串
     //   json.Marshal 函数中使用反射
    jsonStr, err := json.Marshal(monster)
    if err != nil {
    	fmt.Println("json 处理错误 ", err)
    }
    fmt.Println("jsonStr", jsonStr)
    fmt.Println()
    fmt.Println("jsonStr", string(jsonStr))
}
  • 输出结果:

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值