相同点: 都是用来分配内存的内建函数
new: 为所有类型分配内存,并且初始化初始值,并且返回指向类型的指针
make: 只能为 slice, map, chan 分配内存,并且初始化。返回的是 引用类型本身
new 能用于任意类型,而 make 函数只能用于 slice, map, chan 这三种类型
num := new(int) fmt.Println(*num) a := make([]int, 2, 15) b := make(map[string]int) c := make(chan int, 10) fmt.Println(a) fmt.Println(b) fmt.Println(c) 输出: 0 [0 0] map[] 0xc000134000
go 语言有 头等函数(first-class function), 头等函数指得是 函数可以当做变量一样使用; 函数可以当做参数传递给其他函数,可以作为另一个函数的返回值 还可以被赋值给另一个变量
闭包:一个匿名函数变量访问的变量 定义在函数体外的时候。 这种函数叫做闭包函数
// 高阶函数 // 参数是一个带 返回值的函数 func printRes(show func(auth, book string) string) { fmt.Println(show("王大锤", "九阴真经")) } // 高阶函数 // 返回值是函数 func show() func(auth, book string) string { return func(auth, book string) string { return auth + " 不喜欢 " + book } } // 闭包 // 一个匿名函数变量访问的变量 定义在函数体外的时候 这种函数叫做闭包函数 func funN() { x := 99 func() { fmt.Println(x) }() } func firstMethod() { bookName := func() { fmt.Println("我是 王大锤") } bookName() fmt.Printf("bookName 的类型是:%T\n", bookName) f := func(auth, book string) string { return auth + " 学习 " + book } printRes(f) l := show() res := l("王二锤", "葵花宝典") fmt.Println(res) } 运行:firstMethod(): 输出: 我是 王大锤 bookName 的类型是:func() 王大锤 学习 九阴真经 王二锤 不喜欢 葵花宝典
静态类型: 变量声明时候就指定类型
//静态类型 //var age int //var name string
动态类型: 每个接口变量实际上是由 pair (键值)对组成,其中记录了变量的值 和 类型//动态类型 //程序运行时候 系统才能得到的类型 //var in interface{} //in = 10 //in = "我是王大锤"
// 静态类型 与 动态类型 // 静态类型 变量声明时候就指定类型 // 每个接口变量实际上是由 pair (键值)对组成,其中记录了变量的值 和 类型 func typeDynamicStatic() { //静态类型 //var age int //var name string //动态类型 //程序运行时候 系统才能得到的类型 //var in interface{} //in = 10 //in = "我是王大锤" var age int = 100 fmt.Println(age) age2 := (int)(100) fmt.Println(age2) age3 := (interface{})(200) fmt.Println(age3) fmt.Printf("age3 type:%T, value:%v\n", age3, age3) } 输出: 100 100 200 age3 type:int, value:200
go 语言提供一种机制, 能够在运行时 更新变量 和检查他们的值,调用他们的方法和他们支持的内在操作;而不需要在编译时就知道他们的具体类型 这种机制叫做反射
// 但是这种机制 是把 双刃剑 功能强大但是 打码可读性并不理想;而且运行效率不高,
// go 中 reflect 包含实现运行时反射。 reflect 包会帮助识别 interface{} 变量的底层集体类型和具体值type Person struct { name string age int money float64 } func reflectType(x interface{}) { obj := reflect.TypeOf(x) fmt.Println(obj) } func reflectType1(x interface{}) { typeX := reflect.TypeOf(x) valueY := reflect.ValueOf(x) fmt.Println(typeX) fmt.Println(valueY) } func reflectType2(x interface{}) { typeX := reflect.TypeOf(x) fmt.Println(typeX.Kind()) //fmt.Println(typeX.Key()) } func reflectNumField(x interface{}) { if reflect.ValueOf(x).Kind() == reflect.Struct { v := reflect.ValueOf(x) fmt.Println("number of fields:", v.NumField()) for i := 0; i < v.NumField(); i++ { fmt.Printf("Field:%d, type:%T, value:%v\n", i, v.Field(i), v.Field(i)) } } } func goReflect() { var a int64 = 256 reflectType(a) var name string = "王大锤" reflectType(name) fmt.Println("-----------------------------------------") /* reflect.Type 表示interface{} 的具体类型 reflect.TypeOf() 返回 reflect.Type */ var a1 int64 = 1024 reflectType1(a1) var name1 string = "王二锤" reflectType1(name1) fmt.Println("-----------------------------------------") var a2 int64 = 2048 reflectType2(a2) var name2 string = "王三锤" reflectType2(name2) fmt.Println("-----------------------------------------") var person = Person{ name: "玉皇大帝", age: 9999, money: 9999999, } reflectNumField(person) } 输出: int64 string ----------------------------------------- int64 1024 string 王二锤 ----------------------------------------- int64 string ----------------------------------------- number of fields: 3 Field:0, type:reflect.Value, value:玉皇大帝 Field:1, type:reflect.Value, value:9999 Field:2, type:reflect.Value, value:9.999999e+06
反射三定律:
反射可以将 “接口类型变量” 转化为 “反射类型变量”
反射可以将 “反射类型对象” 转化为 “接口类型对象”
如果要修改 “反射类型对象” 其值必须是可写的
func goReflect2() { //反射第一定律:反射可以将 “接口类型变量” 转化为 “反射类型变量” //接口类型变量 ----> 到反射类型变量的转化 var a interface{} = 3.1415 fmt.Printf("接口变量的 类型是:%T, 值为:%v\n", a, a) t := reflect.TypeOf(a) v := reflect.ValueOf(a) fmt.Printf("从接口到反射类型对象:Type 对象类型为: %T\n", t) fmt.Printf("从接口到反射类型对象:Value 对象类型为:%T\n", v) //接口变量的 类型是:float64, 值为:3.1415 //从接口到反射类型对象:Type 对象类型为:*reflect.rtype //从接口到反射类型对象:Value 对象类型为:reflect.Value fmt.Println("-------------------------------------------------") //反射第二定律:反射可以将 “反射类型对象” 转化为 “接口类型对象” i := v.Interface() fmt.Printf("从反射对象到接口变量: 对象类型%T, 值为%v\n", i, i) //使用类型断言进行转换 x := v.Interface().(float64) fmt.Printf("x的类型%T, 值为%v\n", x, x) fmt.Println("-------------------------------------------------") //反射第三定律:如果要修改 “反射类型对象” 其值必须是可写的 var d float64 = 3.14 dy := reflect.ValueOf(d) // dy 不可写, 对于一个不可写的 变量设置值 是会报错的 fmt.Println("dy 是否可写: ", dy.CanSet()) //false //dy.SetFloat(1.96) //panic: reflect: reflect.Value.SetFloat using unaddressable value if dy.CanSet() { dy.SetFloat(1.96) //panic: reflect: reflect.Value.SetFloat using unaddressable value } //如果想要变成 可写的需要传递给指针 dz := reflect.ValueOf(&d).Elem() // dy 不可写, 对于一个不可写的 变量设置值 是会报错的 fmt.Println("dz 是否可写: ", dz.CanSet()) //false dz.SetFloat(1.96) fmt.Println(dz) } 运行输出: 接口变量的 类型是:float64, 值为:3.1415 从接口到反射类型对象:Type 对象类型为: *reflect.rtype 从接口到反射类型对象:Value 对象类型为:reflect.Value ------------------------------------------------- 从反射对象到接口变量: 对象类型float64, 值为3.1415 x的类型float64, 值为3.1415 ------------------------------------------------- dy 是否可写: false dz 是否可写: true 1.96
omitempty :值为 false,0,空指针,空接口。空数组,空切片,空映射, 空字符串 中的一种们就会忽略这个字段
json 获取字段 三种方式
json 获取键值对两种方式:
type PersonMam struct { Name string `json:"name"` Age int `json:"age"` Icon string `json:"icon"` Money float64 `json:"money,omitempty"` } // 结构体中的 tag 标签 func tagStruck() { person := PersonMam{ Name: "苏大强", Age: 56, } jsonData, err := json.Marshal(person) if err != nil { fmt.Println(err) } //omitempty 空对象不展示 fmt.Printf("%s\n", jsonData) //{"name":"苏大强","age":56,"icon":""} person1 := PersonMam{ Name: "苏大强", Age: 56, Money: 2.4545445, } jsonData1, err1 := json.Marshal(person1) if err1 != nil { fmt.Println(err1) } fmt.Printf("%s\n", jsonData1) //{"name":"苏大强","age":56,"icon":"","money":2.4545445} fmt.Println("----------------------------------------------------------") // json 获取字段 三种方式 /* 三种获取字段的方式: 1:filed := reflect.TypeOf(obj).FieldByName("name") 2: filed := reflect.ValueOf(obj).Type().Field(i) 3: filed := reflect.ValueOf(&obj).Elem().Type().Field(i) 获取Tag: tag := filed.Tag 两种获取键值对方式: 获取键值: keyValue := tag.get("key") 没有获取到对应的内容后,会返回空 字符串 keyValue := tag.Lookup("key") */ p := reflect.TypeOf(PersonMam{}) name, _ := p.FieldByName("Name") tag := name.Tag fmt.Printf("name :%v, tag:%s\n", name, tag) KeyValue, _ := tag.Lookup("json") fmt.Println("json KeyValue", KeyValue) // }