go 语言

关键字 new 和 make

相同点: 都是用来分配内存的内建函数

  • 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

 

反射三定律:

  1. 反射可以将 “接口类型变量” 转化为 “反射类型变量

  2. 反射可以将 “反射类型对象” 转化为 “接口类型对象

  3. 如果要修改 “反射类型对象” 其值必须是可写的

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

结构体中的 tag 标签

  • 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)

	//
}

你可能感兴趣的:(go,语法基础特性,golang)