• go基础第二篇:类型


    变量

    go和java一样,是静态类型语言,变量有固定的数据类型,不能修改。

    go用var定义变量,和java定义变量不同,go的变量类型需要放在变量名后面。

    java:String str = "abc";

    go:var str string = "abc"

    当显式提供变量的初始值时,变量类型可以省略,编译器会自动推断。进一步,也可以省略var,此时等号前面要加个冒号:

    var str0 = "abc"

    str1 := "abc"

    可以一次定义多个变量:var x, y int32

    在一次定义多个变量时,变量类型也可以各不相同:

    var a, b = 100, "zhangsan"

    a, b := 100, "zhangsan"

    局部变量未使用时,编译器会报错。全局变量没事。为了规避编译器对未使用的局部变量的检查,可以用_替代局部变量名。

    常量

    用const来定义常量。其他跟定义变量一样,只是const不能省略。

    变量类型

    bool,1个字节

    int、uint,在32位平台是4个字节,在64位平台是8个字节

    int8、uint8、byte(uint8的别称),1个字节。int8取值范围是[-27, 27-1],即[-128, 127]。uint8是无符号int8,取值范围是[0, 255]。

    int16、uint16,2个字节。int16取值范围是[-215, 215-1],即[-32768, 32767]。

    int32、uint32,4个字节。int32的别称是rune,取值范围是[-231, 231-1],即[-2147483648, 2147483647]。uint32是无符号的int32,取值范围是[0, 232-1]。

    int64、uint64,8个字节

    string,和java不同,零值是空字符串。

    字符串操作主要用到2个内置包:strings和strconv

    字符串分割:strings.Split

    字符串拼接:strings.Join

    字符串与数字互转:strconv.Itoa与strconv.Atoi

    指针类型,表示方式是星号后面跟上其他类型,如*int、*string等,值为变量的内存地址。如

    func main() {
        var a int = 10
        var ptr *int = &a
        fmt.Println("ptr= ", ptr)
        fmt.Println("*ptr= ", *ptr)
    }

    *int表示int指针类型,值应该是一个int型变量的内存地址。同理,*string型指针变量的值应该是一个string型变量的内存地址。

    &后面跟变量名,返回此变量指向的内存地址。*后面跟指针类型变量,返回此指针变量指向的值,即该内存地址对应的值。

    数组

    数组定义:

    第一种方式:

    var b [3]int32

    此时3个元素值都为0。可以一个一个赋值

    b[0] = 1

    b[1] = 2

    b[2] = 3

    第二种方式:

    a := [5]int32{}

    此时5个元素值都为0

    也可以直接在大括号中赋值:

    a :=  [5]int32{1, 2, 3, 4, 5}

    由于数组是固定长度的,所以当在大括号中赋值时,中括号中的用于表示数组长度的数字可以由...代替,

    a :=  [...]int32{1, 2, 3, 4, 5}

    第三种方式:

    a := [...]int32{5: 10}

    这种方式表示的意思是,索引为5的元素值为10,5之前的索引的元素值都为0,数组长度为6。

    两个数组可以用==比较,如果两个数据长度一样,且对应索引处的元素一样,则==返回true,否则返回false。

    数组指针与指针数组

    数组的指针

    数组截取

    取前三个:a[0:3],表示从索引0开始,到索引3结束,包括0,不包括3。也可以简写成a[:3]

    取从索引3之后的元素:a[3:]

    取全部:a[:]

    slice

    slice,分片,等同于java中的list,底层也是映射数组。

    slice定义:

    第一种方式:

    var s []int32

    此时s等于nil,需要对s赋值,如s = []int32{},此时s变为一个capacity=0,length=0的slice

    第二种方式:

    s := []string{"a", "b", "c"}

    创建一个capacity=3,length=3,元素分别是"a"、"b"、"c"的slice

    第三种方式:

    s := make([]string, 3)

    创建一个capacity=3,length=3的slice,元素均是空字符串

    s := make([]int32, 3, 5)

    创建一个capacity=5,length=3的slice,3个元素均是0

    用make的话,第一个参数是slice类型,注意不是元素类型,要带着中括号,第二个参数是长度length,第三个参数,假如有,表示容量capacity。如果只有两个参数,则capacity=length。

    用len(s)可得到s的长度。用cap(s)可得到s的容量。

    往分片中添加数据用append,一次可以放多个元素,且append返回值是slice本身:s = append(s, 0, 1)

    slice截取同数组截取一样。

    func main() {
        a := []string{"a", "b", "c"}
        b := a[0:2]
        b[0] = "A"
        fmt.Println(a)
        fmt.Println(b)
        b = append(b, "d")
        fmt.Println(a)
        fmt.Println(b)
    }

    以上,对slice b某索引处元素赋值或者slice b append一个元素后,会影响slice a,因为b是从a截取所得,和a指向的是同一个数组。但是,如果append后b的capacity不够了,要扩容,这个时候b会指向一个新的数组,就不会影响slice a。slice b指向的新数组的capacity值是原来的2倍,如果一次append很多元素的话,2倍原来capacity小于新的length,则新的capacity就等于length。换句话说,新的capacity=max(2*原来capacity, 新length)。

    slice copy

    copy(dst []Type, src []Type),入参是两个slice,把后一个slice的内容复制到前一个slice中。这个copy函数很是个性,与其说是复制,不如说是替换。

    场景一:

    假如两个slice长度一样,则第一个slice的全部内容将会被第二个slice的内容替换。

    场景二:

    假如第一个slice的长度大于第二个slice的长度,比如说第一个slice长度为5,第二个slice长度为3,则第一个slice的前3个元素会被第二个slice的内容替换,后2个元素不变。

    场景三:

    假如第一个slice的长度小于第二个slice的长度,比如说第一个slice长度为3,第二个slice长度为5,则第一个slice的内容会被第二个slice的前3个元素替换。

    slice排序

    用sort包,示例sort.Ints([]int),sort.strings([]string)

    map

    map定义:

    第一种方式:

    m := map[string]string{}

    m := map[string]int{"one": 1, "two": 2}

    key的类型用中括号包裹,value的类型紧跟在key类型的后面。

    第二种方式:

    m := make(map[string]string)

    make关键字既可以用于构造slice,也可用于构造map,但是不能用于构造数组。

    map的put操作:

    m["one"] = 100

    与java不同的是,在访问的key不存在时,仍会返回零值(字符串的话就是空字符串),而不会返回nil。那么如何实现java map的containsKey功能呢,我们可以把m["one"]赋值为两个变量,第二个变量如果为true,就表示map中有这个key,如果为false,则表示map中没有这个key。如下:

    one, ok := m["one"]
    if ok {
        println("存在", one)
    } else {
        println("不存在one")
    }

    map的delete操作:delete(map, key)

    如delete(m, "one")

    map的遍历操作:

    还是用for...range语法,只不过for...range的第一个参数是key,第二个参数是value。如下:

    for k, v := range m {
        println(k, v)
    }

    value的类型除了常规的数字、字符串等类型外,还可以是个函数。如下:

    m := map[int]func(op int) int{}
    println(len(m))
    m[1] = func(op int) int {
        return op
    }
    m[2] = func(op int) int {
        return op * op
    }
    m[3] = func(op int) int {
        return op * op
    }
    println(len(m))
    result := m[2](5)
    println(result)

    m的每个key分别对应不同的函数,通过key取出来直接可以用对应的函数。

    变量名首字母大小写决定了其作用域。首字母大写的,可被包外引用,而小写则仅能在包内使用。

  • 相关阅读:
    UVA 11991 Easy Problem from Rujia Liu(map,vector的使用)
    UVA 11995 I Can Guess the Data Structure! (STL应用)
    HDU 2795 Billboard(线段树,单点更新)
    HDU 1394 Minimum Inversion Number (线段树,单点更新)
    UVA 11827 Maximum GCD(读入技巧,stringstream的使用)
    contest 2 总结
    Const 1 总结
    开始进行大量题目练习
    函数式线段树的个人理解
    poj 2318 TOYS
  • 原文地址:https://www.cnblogs.com/koushr/p/12746350.html
Copyright © 2020-2023  润新知