9.2派生/复杂数据类型
指针
- 基本数据类型,变量存的就是值,也叫值类型
- &变量名 可获取变量的内存地址
- 指针类型,其变量存的是一个地址,这个地址指向的空间存的才是值,比如 var ptr *int = &num
- 获取指针类型所指向的值,使用 *
细节说明: - 值类型,都有对应的指针类型,形式为*数据类型
- 值类型包括:基础数据类型int、float、bool、string,数组和结构体 引用类型:指针、切片slice、map、管道chan、接口interface
特点: - 值类型:变量直接存储值,内存通常在栈中分配
- 引用类型:变量存储的是一个地址,地址对应的空间才真正存储值, 内存通常在堆区分配,当没有任何变量引用这个地址时, 该地址对应的数据空间就成为一个垃圾,由gc来回收
package main
import (
"fmt"
)
func main() {
var i int = 10
//通过&变量名获取内存地址
fmt.Println("i的内存地址是", &i)
var ptr *int = &i
fmt.Printf("ptr=%v \n", ptr) //内存地址
fmt.Printf("ptr的地址是%v \n", &ptr) //内存地址
fmt.Printf("ptr type is %T *ptr type is %T\n", ptr, *ptr) //类型
fmt.Printf("ptr值是%v\n", *ptr) //值
//修改指针变量ptr的值,被引用变量i的值也会被改变,因为都是一个内存地址
*ptr = 99
fmt.Println(i, *ptr)
//修改变量i的值后,指针变量ptr的值也会被改变,因为都是一个内存地址
i = 1
fmt.Println(i, *ptr)
//不报错,但是不要这样用
var int string = "hari"
fmt.Printf(int)
var i int = 10
//通过&变量名获取内存地址
fmt.Println("i的内存地址是", &i)
//fmt.Println(model.HeroName)
}
-
以下类型后面专项说明:数组、结构体struct、管道chan、函数func、切片slice、接口interface、map
-
如果不想使用一个包,但是不想删除,前面加_解决
10、标识符的命名规范
- 1)go对各种变量、方法或函数邓命名使用的字符序列成为标识符
- 2)凡是可以自己起名字的地方,都属于标识符
命名规则
- 1)字母大小写、0-9、_ 组成
- 2)不可以数字开头
- 3)严格区分大小写
- 4)不能包含空格
- 5)下划线_是一个特殊的标识符,成为空标识符,对应的值会被忽略,做为占位符使用
- 6)不能使用系统保留关键字(25个)做为标识符
注意事项
- int float32 等做为标识符代码可以运行,但是不要这样使用
- 包名和文件夹名称尽量保持一致,简短有意义,不要和标准库冲突
- 变量名、函数名、常量名使用驼峰法 const minReadBufferSize
- 如果变量名、函数名、常量名首字母大写,则可以被其他的包访问,否则只能本包内使用 预定标识符:基础数据类型、内嵌函数 共36个
常量
- 常量使用const声明
- 常量在定义的时候,必须初始化
- 常量不能修改
- 常量只能修饰bool、数值类型、string类型
- 常量定义时支持类型推导写法
- golang中没有常量必须大写的要求,常量仍然遵守首字母大小写来控制访问范围的规则
- iota是golang语言的常量计数器,只能在常量的表达式中使用。iota在const关键字出现时将被重置为0(const内部的第一行之前),const中每新增一行常量声明将使iota计数一次(
iota可理解为const语句块中的行索引)。使用iota能简化定义,在定义枚举时很有用。可以使用下划线跳过不想要的值。
//2种写法
//简洁写法
const (
a = 1
b = 2
)
//专业写法
const (
a = iota // a=0
b // b=1
c // c=2
d // d=3
)