go学习笔记类型

类型转换

package main

func main() {
    var b byte = 100
    var n int = b // //隐式转换不支持,会报错
    //var n int = int(b)//显示转换
    println(n)
}

其他值不能当作bool值使用

package main

func main() {
    a := 100
    if a {
        printf("aaa")
    }
}

字符串

字符串是不可变值类型,内部用指针指向UTF-8字节数组
默认值是控制符串””
用索引号访问某字节,如s[i]
不能用序号获取字节元素指针。&s[i]非法
不可变类型,无法修改字节数组
字节数组尾部不包含NULL
使用反引号定义不做转义处理的原始字符串,支持跨行
package main

func main() {
    s := `abc
    asdfa
    c
    `
    println(s)  //结果就是字符串
}
连接跨行字符串时,”+”必须在上一行末尾,否则导致编译错误
package main

func main() {
    s := "hello!" +
        "world!"

    println(s)  //输出结果为hello!world!
}
支持用两个索引号返回子串
package main

func main() {
    s := "hello," +
        "world!"

    s1 := s[:5]
    s2 := s[7:]
    s3 := s[1:7]
    println(s1, s2, s3) //hello orld! ello,w
}
单引号字符创常量表示Unicode Code Point,支持\uFFFF,\U7FFFFFFF,\xFF格式
package main

func main() {
    println("%T\n", 'a')
    var c1, c2 rune = '\u6211', ' '
    println(c1 == ' ', string(c2) == "\xe4\xbb\xac")
}
要修改字符串,必须先将其转换成[]rune或[]byte,完成后再转换为string,这两种方式都会重新分配内存,并复制字节数组
package main

func main() {
    s := "abcd"
    bs := []byte(s)
    bs[1] = 'B'
    println(string(bs)) //aBcd

    u := "电脑"
    us := []rune(u)
    us[1] = '话'
    println(string(us)) //电话
}
用for循环遍历字符串时,也有byte和rune两种方式
package main
import "fmt"

func main() {
    s := "abcd语言"
    for i := 0; i<len(s); i++ {
        fmt.Printf("%c", s[i])  //abcd语言    byte方式
    }

    for _, r := range s {
        fmt.Printf("%c", r)     //abcd语言    rune方式
    }
}

指针

默认值为nil,没有NULL常量
操作符”&”取变量地址,”*”透过指针访问目标对象
不支持指针运算,不支持”->”运算符,直接用”.”访问目标成员
package main
import "fmt"

func main() {
    type data struct{   //申明一个data的数据结构
        a int
    }

    var d = data{1234}  //赋值d的初始值为data类型

    var p *data //申明p的类型
    p = &d

    fmt.Printf("%p, %v\n", p, p.a)  //0xc42000a2a0, 1234
}
不能用指针做加减法运算
package main

func main() {
    x := 1234
    p := &x
    p++ //报错
}
可以在unsafe.Pointer和任意类型指针间进行转换
package main
import (
    "fmt"
    "unsafe"
)

func main() {
    x := 0x12345678
    p := unsafe.Pointer(&x)
    n := (*[4]byte)(p)
    for i := 0; i < len(n); i++ {
        fmt.Printf("%X ", n[i]) //78 56 34 12
    }
}
返回局部变量的指针是安全的,编译器会根据需要将其分配在GC Heap上
package main

func main() {
    println(test())
}

func test() *int {
    x := 100
    return &x
}
将Pointer转换成uintptr,可变相进行指针运算
package main

import (
        "fmt"
        "unsafe"
)

func main() {
    d := struct {
        s string
        x int
    }{"abc", 100}

    //uintptr是goland的内置类型,是存储指针的整型,用于指针运算的;unsafe.Pointer是单纯的通用指针类型,用于转换不同类型指针,它不可以参与指针运算
    p := uintptr(unsafe.Pointer(&d))
    //获取x的偏移量
    p += unsafe.Offsetof(d.x)
    //unsafe.Pointer指向一个Int类型的地址
    p2 := unsafe.Pointer(p)
    px := (*int)(p2)
    *px = 200

    fmt.Printf("%#v\n", d)  //struct { s string; x int }{s:"abc", x:200}
}

自定义类型

可将类型分为命名和未命名两大类,命名类型包括bool,int,string等,而array,slice,map等和具体元素类型,长度等有关,属于未命名类型,具有相同声明的未命名类型被视为同一类型
具有相同基类型的指针
具有相同元素类型和长度的array
具有相同元素类型的slice
具有相同键值类型的map
具有相同元素类型和传送方向的channel
具有相同字段序列(字段名,类型,标签,顺序)的匿名struct
签名相同(参数和返回值,不包括参数名称)的function
方法集相同(方法名,方法签名相同和次序无关)的interface
可用type在全局或函数内定义新类型
package main

func main() {
    type bigint int64
    var x bigint = 100
    println(x)
}
新类型不是原类型的别名,除拥有相同数据存储结构外,他们之间没有任何关系,不会持有原类型任何信息,除非目标类型是未命名类型,否则必须显示转换
package main

import (
    "fmt"
)

func main() {
    type bigint int64
    x := 1234
    var b bigint = bigint(x)
    var b2 int64 = int64(b)

    fmt.Println(b,b2)
}
坚持原创技术分享,您的支持将鼓励我继续创作!