go开发基础(二)


go开发基础2 — go的基础语法(2)

字符串

字符串常用操作

由于UTF-8对占用字节长度的不定性,Go 中的字符串里面的字符也可能根据需要占用 1 至 4 个字节。

a:= `This is a raw string \n`//``表示原样输出字符串,不对\进行转义
var b string="abc"
c:=a+b//+拼接
//下面是strings包的常用操作
import "strings"
strings.HasPrefix(s, prefix string) bool//判断字符串 s 是否以 prefix 开头
strings.HasSuffix(s,suffix string)bool//判断字符串 s 是否以 suffix 结尾
strings.Contains(s, substr string) bool//判断字符串 s 是否包含 substr
strings.Index(s, str string) int//Index 返回字符串 str 在字符串 s 中的索引(str 的第一个字符的索引),-1 表示字符串 s 不包含字符串 str
strings.LastIndex(s, str string) int//最后出现的索引
strings.IndexRune(s string, r rune) int//如果需要查询非 ASCII 编码的字符在父字符串中的位置,建议使用该函数来对字符进行定位
strings.Replace(str, old, new, n) string//将str中前n个old子串变成new,如果n=-1,则将全部old转为new
strings.Count(s, str string) int//用于计算字符串 str 在字符串 s 中出现的非重叠次数,注意是非重叠,即ggg中的gg用这个函数算是返回1
strings.Repeat(s, count int) string//返回count个s,比如(a,3)返回aaa
strings.ToLower(s) string// 将字符串中的 Unicode 字符全部转换为相应的小写字符
strings.ToUpper(s) string//将字符串中的 Unicode 字符全部转换为相应的大写字符
strings.Trim(s, cut string)//将s开头结尾的cut剪掉,如果只想减去空格,则用TrimSpace,如果只想开头,则用TrimLeft,结尾则TrimRight
strings.Split(s, sep string)//以sep作为分隔字符串分隔s,如果拿空格作分隔符,用strings.Fields即可,都是返回一个slice
strings.Join(sl []string, sep string) string//以sep作为分隔符连接s1中元素

字符串与类型转换

字符串与其它类型的转换,通过strconv包实现的。

针对从数字类型转换到字符串,Go 提供了以下函数:

  • strconv.Itoa(i int) string 返回数字 i 所表示的字符串类型的十进制数。

  • strconv.FormatFloat(f float64, fmt byte, prec int, bitSize int) string 将 64 位浮点型的数字转换为字符串,其中 fmt 表示格式(其值可以是 'b''e''f''g'),prec 表示精度,bitSize 则使用 32 表示 float32,用 64 表示 float64。

而任何类型 T 转换为字符串总是成功的。

针对从字符串类型转换为数字类型,Go 提供了以下函数:

  • strconv.Atoi(s string) (i int, err error) 将字符串转换为 int 型。
  • strconv.ParseFloat(s string, bitSize int) (f float64, err error) 将字符串转换为 float64 型。

字符串的遍历

s:="123"
for _,ch:=range s{
    xxx
}

数组与切片

数组的声明与初始化

//类似C的数组,大小在定义后不能更改
var a [3]int//数组声明
var a [4]float32={0.5,2.0,3.0,1.5}//定义
a:=[3]int{1,2,3}//短定义
b:=[...]int{2,3,4,5}//...表示根据元素个数分配大小
c:=[5]int{4:100}//[0,0,0,0,100]这个意思是100的index为4,其他默认为0
d:=[...] int{0: 1, 4: 1, 9: 1} // [1 0 0 0 1 0 0 0 0 1]
const (
    USD Currency = iota // 美元
    EUR                 // 欧元
    GBP                 // 英镑
    RMB                 // 人民币
)
symbol := [...]string{USD: "$", EUR: "€", GBP: "£", RMB: "¥"}//索引:初始值
flag := b==c//如果一个数组的元素类型是可以相互比较的,那么数组类型也是可以相互比较的,当两个数组的所有元素都是相等的时候数组才是相等的。
var graph[2][3]int//多维数组

数组实际上属于一种容器,为值类型(不像 C/C++ 中是指向首元素的指针)

var arr1 = new([5]int)//此时arr1的类型为*[5]int,即数组指针
var arr2 [5]int
arr2=*arr1//相当于作了拷贝
arr2[3]=100//此时不会改变arr1的值,即arr1:&[0 0 0 0 0],arr2:[0 0 0 100 0]
//当然可以像c++一样按引用传递,到函数再提
//也可以按数组指针传递

数组的遍历

a:=[...]int{10,20,30,40,50}
for i:=0;i<len(a);i++{//类C遍历,使用len(a)直接获取数组长度(c++表示羡慕
	xxx
}
for index,num:=range a{//通过range来遍历,如果index用不上可用_来替代
    xxx
}//在该循环中num只是其中元素的拷贝,改变num并不会改变原数组中元素的值
for row := range screen {//多维数组或切片的遍历
	for column := range screen[row] {
		screen[row][column] = 1
	}
}

切片的创建

切片(slice)是对数组一个连续片段的引用(该数组我们称之为相关数组,通常是匿名的),所以切片是一个引用类型(因此更类似于 C/C++ 中的数组类型,或者 Python 中的 list 类型)。

切片的长度可以在运行时修改,最小为 0 最大为相关数组的长度:切片是一个 长度可变的数组

var a []int//不需要声明容量,一个切片在未初始化之前默认为 nil,长度为 0。
arr1:=[...]int{1,2,3}
a=arr1[0:2]//赋值,经典左闭右开,a=[1,2]
b:=arr1[:]//b=[1,2],短定义
//此时a,b两个切片共享这块数组,也就是其任意的修改都会影响数组
a=a[0:3]//切片扩容,但不可以超出数组原长度
var x = []int{2, 3, 5, 7, 11}//类似数组方式初始化,创建了一个长度为 5 的数组并且创建了一个相关切片
//切片在内存中的组织方式实际上是一个有 3 个域的结构体:指向相关数组的指针,切片长度以及切片容量。
n1=len(a)//切片长度
n2=cap(a)//切片容量,一般对于一个数组的相关切片,cap(a)等于数组长度,则必有len(a)小于等于cap(a)
c:=make([]int, 50, 100)//当相关数组还没有定义时,我们可以使用 make() 函数来创建一个切片 同时创建好相关数组,len=50,cap=100,cap可省略
d:=new([100]int)[0:50]//与上面等价
a := [...]int{1, 2, 3}
b := a[0:2]
c := b[0:1]
c[0] = 5//对切片进行切片的修改一样会影响原数组
//切片的遍历与数组相同

new(T) 为每个新的类型T分配一片内存,初始化为 0 并且返回类型为*T的内存地址:这种方法 返回一个指向类型为 T,值为 0 的地址的指针,它适用于值类型如数组和结构体;它相当于 &T{}。其获取的是存储指定变量内存地址的一个变量,对于变量内部结构并不会执行相应的初始化操作

make(T) 返回一个类型为 T 的初始值,它只适用于3种内建的引用类型:切片、map 和 channel。三者在内存中存在多个组成部分, 需要对内存组成部分初始化后才能使用,而make就是对三者进行初始化的一种操作方式

数组与切片函数传参

把一个大数组传递给函数会消耗很多内存。有两种方法可以避免这种现象:

  • 传递数组的指针
  • 使用数组的切片(常用)
func sum(a []int) int {//用切片作为传参通用性更高,因为长度不定,而且内存消耗更小
	s := 0
	for i := 0; i < len(a); i++ {
		s += a[i]
	}
	return s
}

func main() {
	var arr = [5]int{0, 1, 2, 3, 4}
	sum(arr[:])
}

切片的复制与追加

slFrom := []int{1, 2, 3}
slTo := make([]int, 10)
n := copy(slTo, slFrom)//copy函数返回所复制切片的个数,n=3
s1:=[...]int{1,2,3}
s2:=s1[0:2]
s2=append(s2,1)//此时append相当于改变了原数组,即s1:[1,2,1]
s2=append(s2,3)//如果 s 的容量不足以存储新增元素,append 会分配新的切片来保证已有切片元素和新增元素的存储。因此,返回的切片可能已经指向一个不同的相关数组了。s2此时就是这样
s2=append(s2,1,2,3)//也可以添加多个元素
s3:=[]int{1,2,3}
s3=append(s3,s2...)//...相当于把切片切开添加进s3中
a = append(a[:i], a[j:]...)//切除a从i到j-1范围的元素
a=append(a[:i],append([]T{x},a[i:]...)...)//在索引为i处插入元素
a=append(a[:i],append(make([]T,j),a[i:]...)...)//在索引为i处插入长度为j的切片

字符串与切片

s:="string"
c := []byte(s)//字符串切片
c=append(c,s...)//类比数组
substr:=s[1:3]//类比切片
//string为不可变类型,即不可修改单一的值,s[1]='D'是不合法的,所以要转成byte数组来改变值,再string转回来	

文章作者: Wdstql
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Wdstql !
评论
  目录