类型转换
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)
}