Go 数据类型

Posted Palpitate

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Go 数据类型相关的知识,希望对你有一定的参考价值。

数组

package main

import (
    "fmt"
)

//数组:数组是同一类型元素的集合。可以放多个值,但是类型一致,内存中连续存储
// Go 语言中不允许混合不同类型的元素
func main() {

    //1 数组的定义,数组的大小,在定义阶段就确定了,而且不能改
    //定义了一个大小为3的string类型数组,里面可以放3个字符串
    //var names [3]string
    //var ages [3]int8
    //fmt.Println(ages)

    //2 数组赋值
    //var ages [3]int8
    //ages[0]=99
    //ages[2]=88
    //fmt.Println(ages)
    //fmt.Println(ages[1])

    //3 定义并初始化,
    //var ages [3]int=[3]int{1,2,3}
    //var ages [3]int=[3]int{1,2}
    //var ages [3]int=[3]int{}
    //var ages=[3]int{}
    //ages:=[3]int{1,3,4,7}  //不允许多放
    //fmt.Println(ages)

    //4 数组定义并初始化的其他(了解)数组只要定义,长度就固定了,。。。,后面放几个值,数组大小是多少
    //var ages [9]int=[...]int{1,2,3,4,5,6,7,8}   //不支持这个
    //var ages =[...]int{1,2,3,4,5,6,7,8}
    //ages :=[...]int{1,2,3,4,8}
    //fmt.Println(len(ages))

    //5 数组的大小是类型的一部分
    //var a [2]int=[2]int{1,2}
    //var b [2]int=[2]int{1,3}
    //b=a   //如果不是同一种类型,不允许相互赋值
    //fmt.Println(b)

    //6 数组是值类型
    //var a [2]int=[2]int{1,2}
    //fmt.Println(a)
    //test5(a)  //因为数组是值类型,go函数传参,都是copy传递,如果是值类型,函数内改了,不会影响原来的
    //fmt.Println(a)

    //7 数组长度  len()  数组长度在定义阶段已经固定
    //var a [2]int=[2]int{1,2}
    //fmt.Println(len(a))

    //8 数组循环
    //var a =[...]int{7,4,3,5,6,7}
    //fmt.Println(a[99])
    //fmt.Println(len(a))
    //普通循环
    //for i:=0;i<len(a);i++{
    //    fmt.Println(a[i])
    //}

    //通过range来循环  (range不是内置函数,是一个关键字,forifelse),打印出索引
    //for i:=range a{
    //    fmt.Println(i)
    //}

    //如果用一个变量来接收,这个值是可迭代的索引
    //如果用两个变量来接收,这两个变量,一个是索引,一个具体的值
    //for i,value:=range a{
    //    fmt.Println(i)
    //    fmt.Println(value)
    //}
    //把数组循环打印出来
    //for _,value:=range a{
    //    fmt.Println(value)
    //}

    // 9 多维数组
    //var a [3][3]int  //定义
    //a[0][1]=99      //使用
    //fmt.Println(a)

    //定义并赋初值
    //var a [3][3]int=[3][3]int{{1},{1,2,3},{4,4,4}}
    //var s =[3][3]string{{"lqz","xxx","yyy"},{},{}}
    //fmt.Println(s)
    //
    ////循环多维数组
    //for _,value:=range s{
    //    for _,in_value:=range value{
    //        fmt.Println(in_value)
    //    }
    //}

    //10 数组定义并指定位置初始化
    //var names [100]int=[100]int{10:99,99:99}
    //var names [100]int=[100]int{10,11,2,44,99:99,45:88}
    //fmt.Println(names)



}

func test5(a [2]int)  {
    a[0]=99
    fmt.Println(a)

}

 

切片

package main

import "fmt"

//切片:可以变长,
//切片是对底层数组的引用
//切片的改变会影响底层数组
//底层数组的改变,会影响切片
//切片的追加可能会触发扩容,一旦扩容,就不再依赖于原来的底层数组了
func main() {
   //var a []int
   //var b [3]int
   //fmt.Printf("%T",a)
   //fmt.Println()
   //fmt.Printf("%T",b)

   //切片的初始化,从数组切出来
   //var a [10]int
   //b是切片
   //b:=a[:]
   //var b []int=a[:] //从开头切到结尾,赋值给切片b
   //fmt.Println(b)
   //fmt.Printf("%T",b)


   //切片的修改
   //b[0]=99
   //a[0]=888
   //fmt.Println("b-----",b)
   //fmt.Println("a-----",a)

   //切片的长度和容量
   //var a [10]int
   ////var b []int=a[3:]
   //var b []int=a[3:6]
   ////a[3]=999
   //b[2]=222
   ////fmt.Println(a)
   //fmt.Println(b)
   //fmt.Println(len(b)) //3
   //fmt.Println(cap(b)) //7
   //b[3]=999 //不可以 index out of range [3] with length 3

   //var c []int=a[8:]
   //fmt.Println(len(c)) //3
   //fmt.Println(cap(c))


   //切片定义的第二种方式,通过make创建
   //创建了一个长度为2,容量为4的切片
   //var a []int=make([]int,2,4)
   //等同于
   //b:=[4]int{0,0,0,0}
   //a:=b[0:2]
   //fmt.Println(len(a))
   //fmt.Println(cap(a))
   //创建了一个长度为2,容量为2的切片
   //var a []int=make([]int,2)
   //fmt.Println(len(a))
   //fmt.Println(cap(a))

   //扩容,追加切片
   //var a []int=make([]int,2,4)
   //a[0]=111
   //a[1]=222
   //fmt.Println(a)
   ////使用内置函数append
   //a=append(a,333,444)
   //fmt.Println(a)
   //fmt.Println(len(a))
   //fmt.Println(cap(a))
   //临界点到了
   //a=append(a,555)
   //fmt.Println(a)  //111 222 333 444 555
   //fmt.Println(len(a)) //5
   //fmt.Println(cap(a)) //8,自动扩容,在原来容量的基础上扩一倍
   ////切片超过了最大容量,底层数组重新创建,重新指向新的数组
   //a=append(a,666,777,888,999)
   //fmt.Println(a)  //
   //fmt.Println(len(a)) //9
   //fmt.Println(cap(a)) //16


   //切片超过了最大容量,底层数组重新创建,重新指向新的数组
   //var a [10]int
   //b:=a[8:]
   //fmt.Println(b)
   //fmt.Println(len(b))
   //fmt.Println(cap(b))
   //a[9]=999
   //fmt.Println(a)
   //fmt.Println(b)
   //b[0]=888
   //b=append(b,666)
   //fmt.Println("aaaa",a)
   //
   //fmt.Println("------")
   //fmt.Println(b)
   //fmt.Println(len(b))
   //fmt.Println(cap(b))
   ////改掉数组的最后一个值
   //a[9]=1234
   //fmt.Println(b)
   //b[0]=666
   //fmt.Println("----------------")
   //fmt.Println(b)
   //fmt.Println(a)


   //切片的函数传递,切片是引用类型,引用类型的空值是nil
   //所有引用类型的空置都是nil
   //var a[]int=[]int{1,2,3}
   ////长度是3,容量是3
   //fmt.Println(len(a))
   //fmt.Println(cap(a))
   ////fmt.Println(a) //
   //if a==nil{
   // fmt.Println("空的")
   //}else {
   // fmt.Println("不是空")
   //}

   //var a[]int=[]int{1,2,3}
   //test(a)
   //fmt.Println(a) // 999 2 3  影响原来的


   //多维切片
   //var a [][]string=[][]string{{"lqz","egon"},{"zs"},{}}
   //第一层的切片:长度是3 ,容量是3
   //第二层的切片:不确定,根据初始化的情况判断
   //fmt.Println(len(a[2]))
   //fmt.Println(cap(a[2]))

   //var a [][]string=make([][]string,3,4)
   //fmt.Println(a)
   //if a[2]==nil{
   // fmt.Println("")
   //}
   //a[2]=make([]string,3,4)
   //fmt.Println(a[2][0])


   //copy 内置函数
   //var a [10000]int
   //b:=a[:2]
   //b[0]=111
   //b[1]=222
   //
   //var c []int=make([]int,1,4)
   ////把b  copy到c身上
   //copy(c,b)
   //fmt.Println(c)



   var c []int=[]int{3,4,5,6,7,8,9,9}
   //for i:=0;i<len(c);i++{
   // fmt.Println(c[i])
   //}

   for _,v:=range c{
      fmt.Println(v)
   }





}

func test(a []int)  {
   a[0]=999
   fmt.Println(a)// 999 2 3
   a=append(a,777) //如果扩容了,以后再改的,不会影响原来的,如果没扩容,修改会影响原来的
   fmt.Println(a) // 999 2 3 777
   a[0]=444
   fmt.Println(a)// 444 2 3 777

}

 

字符串

package main
//字符串
import (
    "fmt"
)
//len字符串看到的是字节长度
func printBytes(s string) {
    for i:= 0; i < len(s); i++ {
        //fmt.Printf("%x ", s[i])
        fmt.Println(s[i])
    }
}

func main() {
    //name := "Hello World"
    //name := "中国"
    ////printBytes(name)
    //runeLen(name)

}

func runeLen(s string)  {
    //字符长度
    //res:=utf8.RuneCountInString(s)
    //fmt.Println(res)

    //for i:=0;i<utf8.RuneCountInString(s);i++{
    //    fmt.Println((s[i]))
    //}
}

 

maps

package main

import "fmt"

//maps 字典,存储key value的的数据结构

func main() {

    //1 定义
    //int是key值类型,string是value类型
    //引用类型,空值是nil
    //var m map[int]string
    //if m==nil{
    //    fmt.Println("")
    //}

    //定义并初始化
    //var m map[int]string= map[int]string{1:"lqz",2:"egon"}
    //var m = map[int]string{1:"lqz",2:"egon"}
    m:=map[int]string{199:"lqz",200:"egon"}
    fmt.Println(m)

    //添加元素
    m[1]="zhangsan"
    fmt.Println(m)

    //获取元素
    //fmt.Println(m[199])

    //获取的元素不在map中,结果取决于value值的类型
    //fmt.Println(m[2])
    //m1:=map[int]int{1:1}
    //fmt.Println(m1[2])

    //判断元素是否再map中
    //m1:=map[int]int{1:111}
    ////value是key对应的值,如果不存在,为value的空值
    ////flag 是个bool值,如果不存在,是false,如果存在是true
    //value,flag:=m1[1]
    //fmt.Println(value)
    //fmt.Println(flag)

    // 循环map (python字典有序?3.6以后有序了)
    /*
    python字典的底层结构:https://www.cnblogs.com/xiaoyuanqujing/articles/12008689.html
    在Python 3.5(含)以前,字典是不能保证顺序的,键值对A先插入字典,键值对B后插入字典,但是当你打印字典的Keys列表时,你会发现B可能在A的前面。
    但是从Python 3.6开始,字典是变成有顺序的了。你先插入键值对A,后插入键值对B,那么当你打印Keys列表的时候,你就会发现B在A的后面
    [key,key,key]
     */
    //go语言的map是无序的
    //m1:=map[int]int{1:111,4:444,8:888}
    //m1[5]=999
    //m1[3]=888
    //for k,v:=range m1{
    //    fmt.Println("k是",k,"v是",v)
    //}

    //删除元素
    //m1:=map[int]int{1:111,4:444,8:888}
    //delete(m1,4)
    //fmt.Println(m1)

    //map的长度

    //fmt.Println(len(m1))
    //fmt.Println(cap(m1))

    //使用make初始化map,数字不用填,这个数字其实是底层数组的大小
    //m2:=make(map[int]int)
    //m2[1]=11
    //m2[2]=222
    //m2[3]=333
    //m2[4]=444
    //m2[5]=555
    //fmt.Println(m2)

    //map 是引用类型
    //m2:=make(map[int]int)
    //m2[1]=11
    //m2[2]=222
    //m2[3]=333
    //m2[4]=444
    //
    //test6(m2)
    //fmt.Println(m2)
    //map 之间不能使用 == 操作符判断,== 只能用来检查 map 是否为 nil
    //m2:=make(map[int]int)
    //m2[1]=11
    //
    //m3:=make(map[int]int)
    //m3[1]=11
    //
    ////两个map之间不允许直接比较
    //if m2==nil{
    //
    //}

}

func test6(m map[int]int)  {
    m[1]=999


}

 

指针

package main

import "fmt"

//指针:变量,存内存地址
//指针是一种存储变量内存地址的变量。
//取地址符号 &  ,写在一个变量前,表示取该变量的地址
//* 放在类型前,表示该类型的指针
//* 放在变量前,表示解引用(取该地址对应的值)
func main() {
   //var a int=10
   ////指针类型的变量
   ////b:= &a
   //var b *int=&a
   ////fmt.Println(b)
   //
   ////c:=&b
   //var c **int=&b
   //
   //var d ***int=&c
   //fmt.Println(d)
   //
   //fmt.Println(***d)


   //指针的0值:<nil>,引用类型

   //var a *int
   //fmt.Println(a)

   //指针的解引用
   //s:="lqz"
   ////s_p:=&s
   //var s_p *string=&s
   //fmt.Println(*s_p)

   //向函数传递指针参数
   //var a =10
   //test2(&a)
   //fmt.Println(a)
   //s:="lqz"
   //test3(&s)
   //fmt.Println(s)

   //不要向函数传递数组的指针,而应该使用切片

   //var a=[4]int{6,8,9}  //6,8,9,0
   //test4(&a)  //取了数组的地址,传入了test4
   //fmt.Println("-----",a)
   //
   //test5(a[:])
   //fmt.Println("-----",a)

   //指针不支持运算(c语言指针支持运算)
   //var a =[3]int{9,7,6}
   //b:=&a
   ////b++  //不支持
   //fmt.Println(b)


   //  指针数组和数组指针

   var a *[3]int    //指向数组的指针  指向这种数组的指针[3]int    
   a=&[3]int{1,2,43}
   fmt.Println(a)

   var b [3]*int  //大小为3,内部放int类型的指针   
   a1,a2,a3:=10,20,30
   b[0]=&a1
   b[1]=&a2
   b[2]=&a3

   fmt.Println(b)




}

func test4(a *[4]int)  {
   //(*a)[0]=999   //解引用,改值

   a[0]=999   //等同于上面,数组的指针不需要解引用再通过索引取值,直接通过索引取值即可
   fmt.Println(a)
}

func test5(a []int)  {
   a[0]=999
   fmt.Println(a)
}
func test2(a *int)  {
   fmt.Println(a)//地址
   fmt.Println(*a) //解引用   10
   *a=100
}

func test3(a *string)  {
   fmt.Println(*a)
   *a="ssssss"

}

 

 

 

 

 

 

 

 

 

 

以上是关于Go 数据类型的主要内容,如果未能解决你的问题,请参考以下文章

Go 系列教程 —— 17. 方法

解决go: go.mod file not found in current directory or any parent directory; see ‘go help modules‘(代码片段

你知道的Go切片扩容机制可能是错的

Go切片实现

从零开始学Go之容器:切片

golang代码片段(摘抄)