golang学习笔记-struct


在放弃的边缘打滚……
等学完了估计也就忘完了,刚看到之前的笔记发现都陌生得不行,而且之前还有一个有疑问的点说要记录一下,间隔时间长了都忘记是什么了。
虽然markdown很潮流但是也用的非常少,所以还是切换到md模式来记录下,顺便唤起md的记忆
在这里插入图片描述



struct 结构体基础概念
struct 可以看成是golang中的类,是golang面向对象的体现

package main
import (
	"fmt"
)
//Animal 动物 --结构体注释的方式 结构体名 空格 注释
type Animal struct {
	Name string
	Age byte
}

//MulitAttribute 多类型属性
type MulitAttribute struct {
	I *int
	Arr [3]int
	Sli []string
	Mp map[string]string
}
func main() {
	//定义结构体
	var cat Animal
	cat.Name = "cat"
	cat.Age = 2
	//需与结构体定义的属性顺序一致
	dog := Animal{"dog", 3}
	//最后的逗号不可省略
	fish := Animal{
		Name : "fish",
		Age : 4,
	}
	fmt.Println(cat, dog, fish)

	//注意不同类型属性的赋值
	matr := MulitAttribute{}
	//new函数返回指针
	matr.I = new(int)
	matr.Sli = make([]string, 2, 4)
	matr.Mp = make(map[string]string, 2)
	fmt.Println(matr)
	
	i := 9
	matr.I = &i
	
	matr.Arr[0] = 1
	matr.Arr[1] = 2
	matr.Arr[2] = 3

	matr.Sli[0] = "sli01"
	matr.Sli[1] = "sli02"

	matr.Mp["name"] = "demo"

	fmt.Println(matr)
	fmt.Printf("I = %v, Arr = %v, Sli = %v, Mp = %v \n", 
			*matr.I, matr.Arr, matr.Sli, matr.Mp)	
}

结构体是值拷贝

package main

import "fmt"

type Demo struct {
	Str string
	Arr [3]int
	Sli []string
	Mp  map[string]string
}

func main() {
	first := Demo{}
	first.Str = "first"
	first.Arr = [3]int{1, 2, 3}
	first.Sli = make([]string, 2, 3)
	first.Sli[0] = "first01"
	first.Sli[1] = "first02"

	first.Mp = make(map[string]string, 1)
	first.Mp["name"] = "first"
	fmt.Printf("first地址: %p \n", &first)
	fmt.Println(first)

	second := first
	fmt.Println(second)
	fmt.Printf("first地址: %p, second地址:%p \n", &first, &second)

	second.Str = "second"
	second.Arr = [3]int{4, 5, 6}
	second.Sli[0] = "second01"
	second.Sli[1] = "second02"
	second.Mp["name"] = "second"
	//对了,这个就是我刚刚忘记的那个点
	//非引用类型的属性值发生了改变,但引用类型的值被覆盖比如slice 和 map的值被覆盖
	fmt.Println("first: ", first)
	fmt.Println("second: ", second)

	fmt.Printf("first str 地址: %p , arr 地址: %p, sli 地址: %p, mp 地址: %p \n",
		&first.Str, &first.Arr, &first.Sli, &first.Mp)
	fmt.Printf("second str 地址: %p , arr 地址: %p, sli 地址: %p, mp 地址: %p \n",
		&second.Str, &second.Arr, &second.Sli, &second.Mp)

	//考虑到在之前学习slice时发现 当slice添加元素扩充容量后 slice原有的地址改变相当于
	//新创建的slice与原有的无相互关联,此处将slice和map都增加到超出原有的容量
	second.Sli = append(second.Sli, "second03")

	second.Mp["addr"] = "second-addr"
	second.Mp["attribute"] = "second-attribute"

	fmt.Println("------------***--------------")
	fmt.Println("first: ", first)
	fmt.Println("second: ", second)

	fmt.Printf("first str 地址: %p , arr 地址: %p, sli 地址: %p, mp 地址: %p \n",
		&first.Str, &first.Arr, &first.Sli, &first.Mp)
	fmt.Printf("second str 地址: %p , arr 地址: %p, sli 地址: %p, mp 地址: %p \n",
		&second.Str, &second.Arr, &second.Sli, &second.Mp)
	//从结果看,超出容量的slice变成了新slice故与原有slice无关了,但map增加元素超出初始容量并没有直接变化
	//故重新赋值时也与原有map无关
	second.Mp = make(map[string]string, 2)
	fmt.Println("------------***--------------")
	fmt.Println("first: ", first)
	fmt.Println("second: ", second)

	fmt.Printf("first str 地址: %p , arr 地址: %p, sli 地址: %p, mp 地址: %p \n",
		&first.Str, &first.Arr, &first.Sli, &first.Mp)
	fmt.Printf("second str 地址: %p , arr 地址: %p, sli 地址: %p, mp 地址: %p \n",
		&second.Str, &second.Arr, &second.Sli, &second.Mp)
	//综上,结构体的值拷贝特性值得注意的是结构体内部属性的类型所展现的不同区别,这个坑暂时先留着吧
}


golang结构体的属性信息(名称,类型,个数)完全一致时可以进行强转

package main

import "fmt"

type A struct {
	Name string
}
type B struct {
	Name string
}
type C struct {
	Addr string
}

//结构体进行type重新定义(相当于取别名),golang认为是新的数据类型,但是可以进行强制转换
type AnotherA A

func main() {
	a := A{"a"}
	fmt.Println(a)
	var b B
	//不可以直接赋值 a = b,但可以进行强转
	b = B(a)
	fmt.Println(b)
	fmt.Printf("a 地址: %p, b 地址: %p \n", &a, &b)
	//结构体属性不一致不可强转 c := C(a)

	//AnotherA 为type对A进行重新定义的类型,AnotherA为新类型但可以强转
	var anotherA AnotherA
	// anotherA = a 不可直接赋值
	anotherA = AnotherA(a)
	fmt.Printf("anotherA 类型 %T, 地址 %p \n", anotherA, &anotherA)

}

结构体属性的首字母大小写与可见性有关

package main

import (
	"encoding/json"
	"fmt"
)

type Monster struct {
	Name      string
	attribute string
}

type Demon struct {
	Name  string
	Skill string
}

type Devil struct {
	Name string `json:"name"`
	Age  int    `json:"age"`
}

func main() {
	m := Monster{"monster", "m"}
	d := Demon{"demon", "d"}
	//字段首字母小写则意味着访问权限受限,导致json包执行marshal方法时无法访问到该字段
	mbytes, _ := json.Marshal(m)
	dbytes, _ := json.Marshal(d)
	fmt.Println("m json ", string(mbytes))
	fmt.Println("d json ", string(dbytes))
	//为兼容其他语言习惯(属性首字母大小写问题),golang通过将struct的属性设置tag用于序列化及反序列化
	dv := Devil{"devil", 1000}
	dvbytes, _ := json.Marshal(dv)
	fmt.Println("dv json ", string(dvbytes))

	//go 底层对结构体的指针类型做了相应优化
	var ms *Monster = &m
	//按照定义逻辑写法
	fmt.Println((*ms).Name)
	//可以简写省去括号
	fmt.Println(ms.attribute)
}


还说把方法/继承/接口放一起的,还是算了吧


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值