golang基础-数组、切片创建_内存_底层实现_修改值_拷贝_循环、string与切片

前端之家收集整理的这篇文章主要介绍了golang基础-数组、切片创建_内存_底层实现_修改值_拷贝_循环、string与切片前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

数组

数组:是同一种数据类型的固定长度的序列
数组定义:var a [len]int,比如:var a[5]int,一旦定义,长度不能变
长度是数组类型的一部分,因此,var a[5] int和var a[10]int是不同的类型
数组可以通过下标进行访问,下标是从0开始,最后一个元素下标是:len-1
访问越界,如果下标在数组合法范围之外,则触发访问越界,会panic
数组是值类型,因此改变副本的值,不会改变本身的值

package@H_301_14@ main

import@H_301_14@(
    "fmt"@H_301_14@

)


func@H_301_14@ main() {
    //为数组索引赋值@H_301_14@
    var@H_301_14@ a [5@H_301_14@]int@H_301_14@
    a[0@H_301_14@] = 10@H_301_14@
    fmt.Println(a)

    //遍历数组2种方法@H_301_14@
    for@H_301_14@ i:=0@H_301_14@;i<len@H_301_14@(a);i++{
        fmt.Println(a[i])
    }

    for@H_301_14@ i,v := range@H_301_14@ a{
        fmt.Println(i,v)
    }
    //值传递@H_301_14@
    test()

    var@H_301_14@ aa [5@H_301_14@]int@H_301_14@ 
    //通过方法参数值传递@H_301_14@
    test1(aa)
    fmt.Println(aa)
    //传递地址值@H_301_14@
    test2(&aa)
    fmt.Println(aa)


    //数组初始化5种方式@H_301_14@
    var@H_301_14@ arr1 [5@H_301_14@]int@H_301_14@ = [5@H_301_14@]int@H_301_14@{1@H_301_14@,2@H_301_14@,3@H_301_14@,4@H_301_14@,5@H_301_14@}
    fmt.Println(arr1)
    var@H_301_14@ arr2 = [5@H_301_14@]int@H_301_14@{1@H_301_14@,5@H_301_14@}
    fmt.Println(arr2)

    var@H_301_14@ arr3 = [...]int@H_301_14@{1@H_301_14@,5@H_301_14@,6@H_301_14@}
    fmt.Println(arr3)
    var@H_301_14@ arr4 = [...]int@H_301_14@{1@H_301_14@:1@H_301_14@,2@H_301_14@:2@H_301_14@}
    fmt.Println(arr4)

    var@H_301_14@ arr5 = [5@H_301_14@]int@H_301_14@{1@H_301_14@:2@H_301_14@,3@H_301_14@:4@H_301_14@}
    fmt.Println(arr5)


}

func@H_301_14@ test(){
    var@H_301_14@ a [5@H_301_14@]int@H_301_14@
    b := a
    b[0@H_301_14@] = 100@H_301_14@
    fmt.Println(a)
}

func@H_301_14@ test1(arr [5@H_301_14@]int@H_301_14@){
    arr[0@H_301_14@] = 100@H_301_14@
}
func@H_301_14@ test2(arr *[5@H_301_14@]int@H_301_14@){
    (*arr)[0@H_301_14@] = 100@H_301_14@
}

输出如下:

[10@H_301_14@ 0@H_301_14@ 0@H_301_14@ 0@H_301_14@ 0@H_301_14@]
10@H_301_14@
0@H_301_14@
0@H_301_14@
0@H_301_14@
0@H_301_14@
0@H_301_14@ 10@H_301_14@
1@H_301_14@ 0@H_301_14@
2@H_301_14@ 0@H_301_14@
3@H_301_14@ 0@H_301_14@
4@H_301_14@ 0@H_301_14@
[0@H_301_14@ 0@H_301_14@ 0@H_301_14@ 0@H_301_14@ 0@H_301_14@]
[0@H_301_14@ 0@H_301_14@ 0@H_301_14@ 0@H_301_14@ 0@H_301_14@]
[100@H_301_14@ 0@H_301_14@ 0@H_301_14@ 0@H_301_14@ 0@H_301_14@]
[1@H_301_14@ 2@H_301_14@ 3@H_301_14@ 4@H_301_14@ 5@H_301_14@]
[1@H_301_14@ 2@H_301_14@ 3@H_301_14@ 4@H_301_14@ 5@H_301_14@]
[1@H_301_14@ 2@H_301_14@ 4@H_301_14@ 5@H_301_14@ 6@H_301_14@]
[0@H_301_14@ 1@H_301_14@ 2@H_301_14@]
[0@H_301_14@ 2@H_301_14@ 0@H_301_14@ 4@H_301_14@ 0@H_301_14@]

切片

切片:切片是数组的一个引用,因此切片是引用类型
切片的长度可以改变,因此,切片是一个可变的数组

切片遍历方式和数组一样,可以用len()求长度
cap可以求出slice最大的容量,0 <= len(slice) <= (array),其中array是slice引用的数组
切片的定义:var 变量名 []类型,比如 var str []string var arr []int

package@H_301_14@ main

import@H_301_14@(
    "fmt"@H_301_14@

)


func@H_301_14@ main() {
    var@H_301_14@ slice []int@H_301_14@
    var@H_301_14@ arr [5@H_301_14@]int@H_301_14@ = [5@H_301_14@]int@H_301_14@{1@H_301_14@,5@H_301_14@}
    slice = arr[2@H_301_14@:5@H_301_14@]
    fmt.Println(slice)
    //长度@H_301_14@
    fmt.Println(len@H_301_14@(slice))
    //最大容量@H_301_14@
    fmt.Println(cap@H_301_14@(slice))

    slice = slice[0@H_301_14@:1@H_301_14@]
    fmt.Println(len@H_301_14@(slice))
    fmt.Println(cap@H_301_14@(slice))

    //切片的其他声明方法@H_301_14@
    var@H_301_14@ slice1 []int@H_301_14@ = arr[:]
    fmt.Println(slice1)
    var@H_301_14@ slice2 []int@H_301_14@ = arr[0@H_301_14@:3@H_301_14@]
    fmt.Println(slice2)

    var@H_301_14@ slice3 []int@H_301_14@ = []int@H_301_14@{1@H_301_14@,4@H_301_14@}
    fmt.Println(slice3)

}

输出如下:

2017@H_301_14@/10/24 13:46:43 debugger.go:499: continuing [3 4 5]@H_301_14@
3@H_301_14@
3@H_301_14@
1@H_301_14@
3@H_301_14@ [1 2 3 4 5]@H_301_14@ [1 2 3]@H_301_14@ [1 2 4]@H_301_14@

切片内存如何变化的?

package@H_301_14@ main

import@H_301_14@(
    "fmt"@H_301_14@

)

func@H_301_14@ main() {
    var@H_301_14@ a [5@H_301_14@]int@H_301_14@ = [...]int@H_301_14@{1@H_301_14@,5@H_301_14@}
    //切片@H_301_14@
    s:= a[1@H_301_14@:]
    s[1@H_301_14@] = 100@H_301_14@
    //内存地址一样,修改了s的索引值,也就修改了a的索引值@H_301_14@
    fmt.Printf("%p %p\n"@H_301_14@,s,&a[1@H_301_14@])
    fmt.Println("before a:"@H_301_14@,a)
    fmt.Println(s)


    s = append@H_301_14@(s,10@H_301_14@)
    s = append@H_301_14@(s,10@H_301_14@)

    s[1@H_301_14@] = 1000@H_301_14@
    fmt.Println("after a:"@H_301_14@,a)
    fmt.Println(s) 
    //容量改变,重新分配内存 @H_301_14@
    fmt.Printf("%p %p\n"@H_301_14@,&a[1@H_301_14@])

}

输出如下:

0xc04204c1e8@H_301_14@ 0xc04204c1e8@H_301_14@
before@H_301_14@ a@H_301_14@: [1 2 100 4 5]@H_301_14@
[2 100 4 5]@H_301_14@
after@H_301_14@ a@H_301_14@: [1 2 100 4 5]@H_301_14@
[2 1000 4 5 10 10 10 10 10]@H_301_14@
0xc042014200@H_301_14@ 0xc04204c1e8@H_301_14@
PS@H_301_14@ E@H_301_14@:\golang@H_301_14@\go_pro@H_301_14@\src@H_301_14@\safly@H_301_14@>

简单解释下:

创建一个数组a,初始值为{1,2,3,4,5},然后构造一个从索引1开始的数组切片,{2,3,4,5},这里的切片、数组都是同一块内存地址,然后将s[1]赋值为100,由于内存地址是一样的,所以a为{1,2,100,4,5}
s为[2,100,4,5]
接下来为s切片扩充容量,然后修改了s[1] = 1000,最后s为2 1000 4 5 10 10 10 10 10,a依然是[1 2 100 4 5]
,由于底层算法,扩容后,内存地址a和s的就不同了,s从新创建了一个内存地址0xc042014200

切片的底层代码实现

package@H_301_14@ main

import@H_301_14@(
    "fmt"@H_301_14@

)
/*切片底层形式*/@H_301_14@
type@H_301_14@ slice struct@H_301_14@{
    ptr *[5@H_301_14@]int@H_301_14@
    len@H_301_14@ int@H_301_14@ 
    cap@H_301_14@ int@H_301_14@
}
/*构造一个slice*/@H_301_14@
func@H_301_14@ makeSlice(s slice,cap@H_301_14@ int@H_301_14@) slice{
    s.ptr = new@H_301_14@([5@H_301_14@]int@H_301_14@)
    s.cap@H_301_14@ = cap@H_301_14@
    s.len@H_301_14@ = 0@H_301_14@
    return@H_301_14@ s

}

func@H_301_14@ testSlice(){
    //slice类型@H_301_14@
    var@H_301_14@ a slice 
    a = makeSlice(a,5@H_301_14@)
    a.ptr[0@H_301_14@] = 100@H_301_14@
    fmt.Println(a.ptr)
}

func@H_301_14@ main() {
    testSlice()

}

输出如下:

&[100 0 0 0 0]@H_301_14@

修改切片值、演示切片内存地址

package@H_301_14@ main

import@H_301_14@(
    "fmt"@H_301_14@

)

/*切片会被修改*/@H_301_14@
func@H_301_14@ modify(b []int@H_301_14@){
    b[1@H_301_14@] = 200@H_301_14@
}

func@H_301_14@ modify1(b *[]int@H_301_14@){
    (*b)[1@H_301_14@] = 2000@H_301_14@
}

func@H_301_14@ main() {

    var@H_301_14@ b []int@H_301_14@ = []int@H_301_14@{1@H_301_14@,3@H_301_14@}
    fmt.Println(b)
    //修改切片方法1--直接穿切片@H_301_14@
    modify(b)
    fmt.Println(b)
    //修改切片方法2--传地址值@H_301_14@
    modify1(&b)
    fmt.Println(b)

    //数组不会被修改,参数为数组@H_301_14@
    var@H_301_14@ d [3@H_301_14@]int@H_301_14@ = [...]int@H_301_14@{3@H_301_14@,5@H_301_14@}
    modify3(d)
    fmt.Println(d)

/*演示切片的内存布局*/@H_301_14@
    testSlice5()
}

func@H_301_14@ modify3(b [3@H_301_14@]int@H_301_14@){
    b[1@H_301_14@] = 200@H_301_14@
}
/*演示切片的内存布局*/@H_301_14@
func@H_301_14@ testSlice5(){
    fmt.Println("----------------"@H_301_14@)

    var@H_301_14@ a = [10@H_301_14@]int@H_301_14@{1@H_301_14@,4@H_301_14@}
    b :=a[1@H_301_14@:5@H_301_14@]

    fmt.Printf("%p\n"@H_301_14@,b)
    fmt.Printf("%p\n"@H_301_14@,&a[1@H_301_14@])
    fmt.Println(a,b)

}

输出如下:

[1 2 3]@H_301_14@
[1 200 3]@H_301_14@
[1 2000 3]@H_301_14@
[3 4 5]@H_301_14@
----------------@H_301_14@
0xc0420101e8@H_301_14@
0xc0420101e8@H_301_14@
[1 2 3 4 0 0 0 0 0 0]@H_301_14@ [2 3 4 0]@H_301_14@
PS@H_301_14@ E@H_301_14@:\golang@H_301_14@\go_pro@H_301_14@\src@H_301_14@\safly@H_301_14@>

切片拷贝make\copy\append

package@H_301_14@ main

import@H_301_14@(
    "fmt"@H_301_14@

)

func@H_301_14@ main() {
    var@H_301_14@ a []int@H_301_14@= []int@H_301_14@{1@H_301_14@,6@H_301_14@}
    fmt.Println(a)

    b:= make@H_301_14@([]int@H_301_14@,1@H_301_14@)
    fmt.Println(b)
    //将a的值拷贝到b@H_301_14@
    copy@H_301_14@(b,a)
    fmt.Println(b)
    //将a拷贝到c@H_301_14@
    c:=make@H_301_14@([]int@H_301_14@,10@H_301_14@)
    copy@H_301_14@(c,a)
    fmt.Println(c)

    //append自己@H_301_14@
    d :=append@H_301_14@(c,c...)
    fmt.Println(d)

    //append元素@H_301_14@
    e:=append@H_301_14@(c,4@H_301_14@)
    fmt.Println(e)
}

输出如下:

PS E:\golang@H_301_14@\go@H_301_14@_pro\src@H_301_14@\safly@H_301_14@> go run demo.go
[@H_301_14@1 2 3 4 5 6]@H_301_14@
[@H_301_14@0]@H_301_14@
[@H_301_14@1]@H_301_14@
[@H_301_14@1 2 3 4 5 6 0 0 0 0]@H_301_14@
[@H_301_14@1 2 3 4 5 6 0 0 0 0 1 2 3 4 5 6 0 0 0 0]@H_301_14@
[@H_301_14@1 2 3 4 5 6 0 0 0 0 2 4]@H_301_14@
PS E:\golang@H_301_14@\go@H_301_14@_pro\src@H_301_14@\safly@H_301_14@>

string与slice

string底层就是一个byte的数组,因此,也可以进行切片操作

string本身是不可变的,因此要改变string中字符,需要如下操作

package@H_301_14@ main@H_301_14@

import@H_301_14@(
    "fmt@H_301_14@"

)

func@H_301_14@ main@H_301_14@() { s@H_301_14@:="hellogo"@H_301_14@ s1:=s[0@H_301_14@:3@H_301_14@] s2:=s[2@H_301_14@:] fmt.Println(s1)@H_301_14@ fmt.Println(s2)@H_301_14@ testModifyStr()@H_301_14@ @H_301_14@@H_301_14@@H_301_14@}

func@H_301_14@ testModifyStr@H_301_14@(){ //带中文s@H_301_14@:="我的hellogo"@H_301_14@ s1:=[]rune(s)@H_301_14@ s1[1@H_301_14@] = 'a'@H_301_14@ str:=string(s1)@H_301_14@ fmt.Println(str)@H_301_14@ aaa := "hello world"@H_301_14@ bbb := []byte(aaa)@H_301_14@ bbb[0@H_301_14@] = 'o'@H_301_14@ str = string(bbb)@H_301_14@ fmt.Println(str)@H_301_14@ @H_301_14@@H_301_14@@H_301_14@}

输出如下:

hel
llogo
我ahellogo
oello world
PS E:\golang@H_301_14@\go@H_301_14@_pro\src@H_301_14@\safly@H_301_14@>

切片循环

package@H_301_14@ main

import@H_301_14@(
    "fmt"@H_301_14@

)

func@H_301_14@ main() {
    var@H_301_14@ a []int@H_301_14@= []int@H_301_14@{1@H_301_14@,6@H_301_14@}
    fmt.Println(a)

    for@H_301_14@ index,val := range@H_301_14@ a {
        fmt.Println(index,val)
    }

    for@H_301_14@ _,val := range@H_301_14@ a {
        fmt.Print` n(val) } } @H_301_14@

输出如下:

PS E:\golang@H_301_14@\go@H_301_14@_pro\src@H_301_14@\safly@H_301_14@> go run demo.go
[@H_301_14@1 2 3 4 5 6]@H_301_14@
0 1
1 2
2 3
3 4
4 5
5 6
1
2
3
4
5
6
PS E:\golang@H_301_14@\go@H_301_14@_pro\src@H_301_14@\safly@H_301_14@>

猜你在找的Go相关文章