golang(二)数据(上)

 

字符串

字符串是不可变字节(byte)序列,本身是一个复合结构。默认以UTF-8编码存储unicode字符。它的默认值是“”,而不是nil。字符串底层就是⼀个byte数组,所以可以和[]byte类型互相转换。

使用“ ‘ ”定义不做转义处理的原始字符串,支持跨行。

func main() {
    s := 'line\r\n,
    line 2'

    println(s);
}

输出:

line\r\n,
    line 2

字符串之中的字符是不能修改的,但是可以将其转换为可变类型([]rune或[]byte),完成之后再转换回来。但是不管如何转换,都需要重新分配内存,并复制数据。字符串是由byte字节组成,所以字符串的长度是byte字节的长度。rune类型用来表示utf8字符,一个rune字符由1个或多个byte组成。

func pp(format string, ptr interface{}) {
    p := reflect.ValueOf(ptr).Pointer()
    h := (*uintptr)(unsafe.Pointer(p))
    fmt.Printf(format, *h)
}

func main() {
    s :="hello,world!"
    pp("s: %x\n", &s)

    bs := []byte(s)
    s2 := string(bs)

    pp(“string to []byte, bs; %x\n”, &bs)
    pp(“[]byte to string, s2; %x\n”, &s2)

    rs := []rune(s)
    s3 := string(rs)

    pp(“string to []rune, rs; %x\n”, &rs)
    pp(“[]rune to string, s3; %x\n”, &s3)
}

有些时候,转换会降低算法的性能,因此可以考虑使用“非安全”方法进行改善。

func toString(bs []byte) string {
    return *(*string)(unsafe.Pointer(&bs))
}

func main() {
    bs := []byte("hello,world!")
    S := toString(bs)

    printDataPointer("bs: %x\n", &bs)
    printDataPointer("s : %x\n", &s)
}

该方法利用了[]byte和string头结构“部分相同”,以非安全的指针类型转换来实现类型“变更”,避免了底层数组复制。在高并发压力下能有效改善执行性能。

使用+拼接字符串也会产生性能问题,每次都必须重新分配内存。可以预分配足够的内存空间,使用strings.Join函数,统计所有参数长度,并一次性完成内存分配操作。

数组

数组是同一类型的元素集合。Go数组下标也是从0开始,因此长度为n的数组下标范围是[0,n-1]。整数数组中的元素默认初始化为0,字符串数组中的元素默认初始化为“”。

var a [3]int   //定义一个数组

数组的初始化有以下几种:

//数组初始化
var a [3]int
a[0] = 10
a[1] = 20
a[2] = 30

var a [3]int = [3]int{10, 20, 30}    //定义时数组初始化

a := [3]int{10, 20, 30}        //定义时数组初始化

a := […]int{10, 20, 30}        //定义时数组初始化

a := [3]int{10}            //定义时数组初始化,未提供初始值的自动初始化为0

a := [3]int{2:10}          //定义时数组初始化,制定索引位置初始化

数组长度是类型的⼀部分

var a [3]int
a[0] = 10
a[1] = 20
a[2] = 30
var b [5]int
b = a            //a、b是不同类型的数组,不能赋值

数组内置函数len和cap都返回第一维长度。

var a [3]int
a[0] = 10
a[1] = 20
a[2] = 30
fmt.Printf(“len:%d\n”, len(a))

数组的遍历

var a [3]int
a[0] = 10
a[1] = 20
a[2] = 30
for i := 0; i < len(a); i++ {     //遍历1
}


for index, val := range a {       //遍历2
}

var a [3][2]int
a[0][0] = 10
a[0][1] = 20
a[1][0] = 30
a[1][1] = 30
a[2][0] = 30
a[2][1] = 30
for index, val := range a {        //二维数组遍历
}

数组的拷贝与传参

//数组是值类型
var a [3]int
a[0] = 10
a[1] = 20
a[2] = 30
b := a
//b拷⻉了数组a中所有元素
b[0] = 1000
fmt.Println(a, b)

//数组是值类型,函数传参也会拷贝
func main() {
    var a [3]int
    a[0] = 10
    a[1] = 20
    a[2] = 30
    modify(a)
    fmt.Println(a)
}
func modify(b [3]int) {
    b[0] = 1000
    return
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值