【Go 基础】

指针

Go语言保留了指针,但与C语言指针有所不同。主要体现在:

  • 默认值 nil
  • 操作符 “&” 取变量地址, “*” 通过指针访问目标对象
  • 不支持指针运算,不支持 “->” 运算符,直接⽤ “.” 访问目标成员
函数new

表达式new(T)将创建一个T类型的匿名变量,所做的是为T类型的新值分配并清零一块内存空间,然后将这块内存空间的地址作为结果返回,而这个结果就是指向这个新的T类型值的指针值,返回的指针类型为*T。

new创建的内存空间位于heap上,空间的默认值为数据类型默认值。如:new(int) 则 *p为0,new(bool) 则 *p为false

func main()  {
   var p1 *int
   p1 = new(int)                     //p1为*int 类型, 指向匿名的int变量
   fmt.Println("*p1 = ", *p1)     	 //*p1 =  0

   p2 := new(bool)             	     //p2为*bool 类型, 指向匿名的bool变量
   fmt.Println("*p2 = ", *p2)     	 //*p2 = false
   *p2 = true
   fmt.Println("*p2 = ", *p2)     	 //*p1 = true
}

指针做函数参数
func swap01(a, b int) {
    a, b = b, a
    fmt.Printf("swap01 a = %d, b = %d\n", a, b)
}

func swap02(x, y *int) {
    *x, *y = *y, *x
}

func main() {
    a := 10
    b := 20

    //swap01(a, b) 	//值传递(传值)
    swap02(&a, &b) 	//地址传递(传引用)
    fmt.Printf("a = %d, b = %d\n", a, b)
}
关于多重赋值

https://www.jianshu.com/p/de95ef71162d

切片(slice)

为什么要有切片?
  1. 数组的容量固定,不能自动拓展。
  2. 值传递。 数组作为函数参数时,将整个数组值拷贝一份给形参(值拷贝内存消耗大)。

在Go语言中,我们几乎可以在所有的场景中,使用切片替换数组使用。

  • 一个slice由三个部分构成:指针、长度和容量。

切片并不是数组或数组指针,它通过内部指针和相关属性引⽤数组⽚段,以实现变⻓⽅案。(后续通过阅读源码深入了解)

切片创建

可以用make关键字:

s := make([]int, 5)

注意:make只能创建slice、map和channel,并且返回一个有初始值(非零)的对象。

切片截取

截取可表示为s[low:high:max]。

  • low:表示下标的起点。
  • high:表示下标的终点(左闭右开,不包括此下标)
  • 长度 len = high – low。
  • 容量 cap = max – low。

长度对应slice中元素的数目;长度不能超过容量,容量一般是从slice的开始位置到底层数据的结尾位置。

切片作为函数参数时,传引用

append函数

append函数会智能的将底层数组的容量增长,一旦超过原底层数组容量,通常以2倍(1024以下)容量重新分配底层数组,并复制原来的数据。

因此,使用append 给切片做扩充时,切片的地址可能发生变化。但,数据都被重新保存了,不影响使用

copy函数

函数 copy 在两个 slice 间复制数据,复制⻓度以 len 小的为准,两个 slice 指向同⼀底层数组。直接对应位置覆盖。

  • copy(目标位置切片, 源切片)

map

Go语言中的map(映射、字典)是一种内置的数据结构,它是一个无序的key-value对的集合,比如以身份证号作为唯一键来标识一个人的信息。

Go语言中并没有提供一个set类型,但是map中的key也是不相同的,可以用map实现类似set的功能。

map的格式:

map[keyType]valueType

在一个map里所有的键都是唯一的,而且必须是支持==和!=操作符的类型,切片、函数以及包含切片的结构类型这些类型由于具有引用语义,不能作为映射的键,使用这些类型会造成编译错误。

注意:map是无序的,我们无法决定它的返回顺序,所以,每次打印结果的顺利有可能不同。

创建map
m := make(map[int]string, 10)   //第2个参数指定容量
赋值
  • 如果新map元素的key与原map元素key相同 ——> 覆盖(替换)

  • 如果新map元素的key与原map元素key不同 ——> 添加

遍历

Map的迭代顺序是不确定的,并且不同的哈希函数实现可能导致不同的遍历顺序。在实践中,遍历的顺序是随机的,每一次遍历的顺序都不相同。

判断map中key是否存在:

value, ok := m[1]
  • 如果key存在,第一个返回值返回value的值。第二个返回值为 true。

  • 如果key存在,第一个返回值返回value的值。第二个返回值为 true。

删除

使用delete()函数,指定key值可以方便的删除map中的k-v映射。

delete(m1, 2) 		//删除key值为2的map

map 做函数参数和返回值,传引用。

结构体

比较

如果结构体的全部成员都是可以比较的,那么结构体也是可以比较的,那样的话两个结构体将可以使用 == 或 != 运算符进行比较,但不支持 > 或 <

做函数参数

传参过程中,实参会将自己的值拷贝一份给形参。因此结构体“传值”操作几乎不会在实际开发中被使用到。近乎100%的使用都采用“传址”的方式,将结构体的引用传递给所需函数。

字符串处理函数

具体可参考Golang标准库文档

除Contains、Join、Trim、Replace等我们学过的字符串处理函数之外,以下函数也常常会被用到。

字符串分割
  • func Split(s, sep string) []string

功能:把s字符串按照sep分割,返回slice

按空格拆分字符串
  • func Split(s, sep string) []string
    功能:把s字符串按照sep分割,返回slice
判断字符串后缀
  • func HasSuffix(s, suffix string) bool
    功能:判断s字符串是否有后缀子串suffix
判断字符串前缀
  • func HasPrefix(s, prefix string) bool
    功能:判断s字符串是否有前缀子串suffix

文件IO

打开、创建文件:
  1. 创建文件 Create: 文件不存在创建,文件存在,将文件内容清空。
  • 参数:name, 打开文件的路径: 绝对路径、相对路径 目录分割符:/
  1. 打开文件 Open: 以只读方式打开文件。文件不存在,打开失败。
  • 参数:name, 打开文件的路径: 绝对路径、相对路径
  1. 打开文件 OpenFile: 以只读、只写、读写 方式打开文件。文件不存在,打开失败。
  • 参1:name, 打开文件的路径: 绝对路径、相对路径

  • 参2:打开文件权限: O_RDONLY、O_WRONLY、O_RDWR

  • 参3:一般传 6

写文件:

按字符串写:

WriteString() --> n个写入的字符个数

n, err := f.WriteString("123")

回车换行: windows: \r\n Linux: \n

按位置写:

Seek(): 修改文件的读写指针位置。

  • 参1: 偏移量。 正:向文件尾偏, 负:向文件头偏

  • 参2: 偏移起始位置:

io.SeekStart: 文件起始位置

io.SeekCurrent: 文件当前位置

io.SeekEnd: 文件结尾位置

返回值:表示从文件起始位置,到当前文件读写指针位置的偏移量。

off, _ := f.Seek(-5, io.SeekEnd)

按字节写:

writeAt(): 在文件制定偏移位置,写入 []byte , 通常搭配 Seek()

  • 参1: 待写入的数据

  • 参2:偏移量

返回:实际写出的字节数。

n, _ = f.WriteAt([]byte(“1111”), off)

读文件:

按行读

  1. 创建一个带有缓冲区的 Reader(读写器)
reader : = bufio.NewReader(打开的文件指针)
  1. 从reader的缓冲区中 ,读取指定长度的数据。数据长度取决于 参数 dlime
buf, err := reader.ReadBytes('\n')  按行读。

判断到达文件结尾:

if err != nil && err == io.EOF

到文件结尾。

文件结束标记,是要单独读一次获取到的。

缓冲区:内存中的一块区域,用来减少物理磁盘访问操作。《计算硬件及组成原理》 —— 机械工业出版社。

按字节读、写文件。

  • read([]byte): 按字节读文件

  • write([]byte):按字节字节

目录操作:

打开目录: OpenFile

打开目录 OpenFile: 以只读方式打开目录。

  • 参1:name, 打开目录的路径: 绝对路径、相对路径

  • 参2:打开目录权限: O_RDONLY

  • 参3:os.ModeDir

返回值: 返回一个可以读目录的 文件指针。

读目录:Readdir

函数原型:

func (f *File) Readdir(n int) ([]FileInfo, error) {
    //参数: 欲打开的目录项个数。 -1 , 表所有
	//返回值:FileInfo :
}

type FileInfo interface {
	Name() string       		// base name of the file
	Size() int64        		// length in bytes for regular files; system-dependent for others
	Mode() FileMode     		// file mode bits
	ModTime() time.Time 	// modification time
	IsDir() bool        		// abbreviation for Mode().IsDir()
	Sys() interface{}   		// underlying data source (can return nil)
}	
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值