文章目录
bool
true false
int uint
int8 uint8 (byte)
func main() {
var x byte
x = '1'
fmt.Println(x)
}
int16 uint16
int32 (rune) uint32
func main() {
var y rune
y = '我'
fmt.Println(y)
}
int64 uint64
float32 / float64
complex64 / complex128 TODO
uintptr TODO
array
func main() {
array := [5]int{1, 2, 3}
var array2 [5]int
array2 = *new([5]int)
array2 = [5]int{1, 2, 3}
fmt.Println(array)
fmt.Println(array2)
}
// [number]Type{} 类型为[number]Type,即同一类型不同长度数组是不同类型
struct
type
type的原始类型和之后的类型可以互相赋值,但结构体必须精确一致(成员变量名字、类型和顺序)。
同一原始类型的不同之后的类型不能互相赋值。
func main() {
var a struct{ x int }
type Node struct{ x int }
a = Node{1}
fmt.Println(a)
type Node2 struct{ x, y float64 }
type Node3 struct{ x, y float64 }
var b Node2
b = struct{ x, y float64 }{y: 1.1}
fmt.Println(b)
//b = struct{ y, x float64 }{y: 1.1}
/*b = struct {
y float64
x float64
}{y: 1.1}*/
b = struct {
x float64
y float64
}{y: 1.2}
fmt.Println(b)
fmt.Printf("%T\n", b)
//b = Node3{}
type Int int
var x Int
x = 1
fmt.Println(x)
}
D:\gopath\src\mygo>go run main.go
{1}
{0 1.1}
{0 1.2}
main.Node2
1
成员函数
成员函数不区分原始型和指针型,不能重复定义。
type Node struct {
a int
}
func (node *Node) Output() string {
return "{!a:" + strconv.Itoa(node.a) + "}"
}
func (node Node) Output2() string {
return "2{!a:" + strconv.Itoa(node.a) + "}"
}
func main() {
var node1 = Node{1}
var node2 = Node{2}
fmt.Println(node1.Output())
fmt.Println(node1.Output2())
fmt.Println(node2.Output())
fmt.Println(node2.Output2())
}
{!a:1}
2{!a:1}
{!a:2}
2{!a:2}
修改成员变量的成员函数
必须定义为func (*Type)…
type Node struct {
a int
}
func (node *Node) Set(x int) {
node.a = x
}
func (node Node) Set2(x int) {
node.a = x
}
func main() {
var node = Node{1}
node.Set(3)
fmt.Println(node)
node.Set2(4)
fmt.Println(node)
(&node).Set(5)
fmt.Println(node)
(&node).Set2(6)
fmt.Println(node)
}
{3}
{3}
{5}
{5}
覆盖
通过type定义新类型重新实现成员函数,进行覆盖。成员函数只适用于本身的类型
type Node struct {
a int
}
type Node2 Node
func (node Node) Output() string {
return fmt.Sprint(node)
}
func (node Node) Output2() string {
return fmt.Sprint(node)
}
func (node2 Node2) Output() string {
return fmt.Sprint("2", node2)
}
func (node2 Node2) Output3() string {
return fmt.Sprint("2", node2)
}
func main() {
node := Node{1}
node2 := Node2{1}
fmt.Println(node.Output())
fmt.Println(node2.Output())
fmt.Println((Node(node2)).Output())
fmt.Println("------")
fmt.Println(node.Output2())
//fmt.Println(node2.Output2())
fmt.Println((Node(node2)).Output2())
fmt.Println("------")
fmt.Println((Node2(node)).Output3())
fmt.Println(node2.Output3())
//fmt.Println((Node(node2)).Output3())
}
D:\gopath\src\mygo>go run main.go
{1}
2{1}
{1}
------
{1}
{1}
------
2{1}
2{1}
输出
对于fmt的Println或Printf("%v %+v"),可以通过func(Type)String() string定义,调用精确匹配的此接口
type Node struct {
a int
}
func (node *Node) String() string {
return "{!a:" + strconv.Itoa(node.a) + "}"
}
func main() {
var node = Node{1}
fmt.Println(node)
fmt.Printf("%T\n", node)
fmt.Printf("%v\n", node)
fmt.Printf("%+v\n", node)
fmt.Printf("%#v\n", node)
fmt.Printf("------")
fmt.Println(&node)
fmt.Printf("%T\n", &node)
fmt.Printf("%v\n", &node)
fmt.Printf("%+v\n", &node)
fmt.Printf("%#v\n", &node)
}
D:\gopath\src\mygo>go run main.go
{1}
main.Node
{1}
{a:1}
main.Node{a:1}
------{!a:1}
*main.Node
{!a:1}
{!a:1}
&main.Node{a:1}
string
正确统计中文字数
func main() {
var s string
s = "abc啊"
fmt.Println(len(s))
fmt.Println(len([]byte(s)))
fmt.Println(len([]rune(s)))
fmt.Printf("%T\n", s[0])
fmt.Printf("%T\n", []byte(s)[0])
fmt.Printf("%T\n", []rune(s)[0])
}
D:\gopath\src\mygo>go run main.go
6
6
4
uint8
uint8
int32
字符串连接效率
字符串反复+和[]byte append追加效率对比
func main() {
seed := time.Now().Unix()
rand.Seed(seed)
var begin time.Time
const number = 100000
var s string
begin = time.Now()
for i := 0; i < number; i++ {
s += strconv.Itoa(rand.Intn(i + 1))
}
fmt.Println(len(s))
fmt.Println(time.Now().Sub(begin).Milliseconds())
rand.Seed(seed)
var b []byte
begin = time.Now()
for i := 0; i < number; i++ {
b = append(b, strconv.Itoa(rand.Intn(i+1))...)
}
fmt.Println(len(b))
fmt.Println(time.Now().Sub(begin).Milliseconds())
}
D:\gopath\src\mygo>go run main.go
460740
3886
460740
8
字符串数字互相转换
func main() {
fmt.Println(fmt.Sprintf("%d", 1234567890))
fmt.Println(strconv.Itoa(1234567890))
a, err := strconv.Atoi("1234567890")
if err != nil {
panic(err)
}
fmt.Println(a)
a, err = strconv.Atoi("123456.7890")
if err != nil {
fmt.Println(err.Error())
return
}
fmt.Println(a)
}
D:\gopath\src\mygo>go run main.go
1234567890
1234567890
1234567890
strconv.Atoi: parsing "123456.7890": invalid syntax
slice []Type
切片构造、初始化、截取、追加、删除
func output(name string, slice []int) {
fmt.Printf("%s %v\tlen:%v\tcap:%v\t%p\n",
name, slice, len(slice), cap(slice), &slice[0])
}
func main() {
s := []int{1, 2, 3, 4, 5}
output("s", s)
a := make([]int, 3, 5)
a = s[1:4]
output("a", a)
// 修改派生切片影响基础切片/数组
fmt.Println("modify slice")
a = append(a, 6)
output("a", a)
output("s", s)
// 基础数组无法容纳将重新分配空间
/*a = append(a, 7)
output("a", a)
output("s", s)*/
// 修改基础数组/切片影响派生切片
fmt.Println("modify base array/slice")
s = append(s[:2], s[3:]...)
output("a", a)
output("s", s)
// 基础数组无法容纳将重新分配空间
s = append(s, 7, 8)
output("a", a)
output("s", s)
}
D:\gopath\src\mygo>go run main.go
s [1 2 3 4 5] len:5 cap:5 0xc0000143c0
a [2 3 4] len:3 cap:4 0xc0000143c8
modify slice
a [2 3 4 6] len:4 cap:4 0xc0000143c8
s [1 2 3 4 6] len:5 cap:5 0xc0000143c0
modify base array/slice
a [2 4 6 6] len:4 cap:4 0xc0000143c8
s [1 2 4 6] len:4 cap:5 0xc0000143c0
a [2 4 6 6] len:4 cap:4 0xc0000143c8
s [1 2 4 6 7 8] len:6 cap:10 0xc000010550
map
map设置,获取,删除,遍历
func main() {
mp := make(map[int]int)
// set 设置键值
mp[1] = 1
mp[2] = 4
mp[3] = 9
// 遍历
for k := range mp {
fmt.Println(k, "=>", mp[k])
}
// 确保键不存在
delete(mp, 0)
delete(mp, 1)
// 获取键
v, ok := mp[1]
fmt.Println("v", v, "ok", ok)
v, ok = mp[2]
fmt.Println("v", v, "ok", ok)
// 遍历
for k, v := range mp {
fmt.Println(k, "=>", v)
}
// 直接输出
fmt.Println(mp)
fmt.Printf("%#v\n", mp)
}
D:\gopath\src\mygo>go run main.go
1 => 1
2 => 4
3 => 9
v 0 ok false
v 4 ok true
2 => 4
3 => 9
map[2:4 3:9]
map[int]int{2:4, 3:9}
chan
channel写入只写,读取只读,关闭只写,关闭后读取
func main() {
go func() {
i := 1
for {
time.Sleep(time.Millisecond * 300)
fmt.Println("clock:", i)
i++
}
}()
var ch = make(chan int)
go func(chin chan<- int) {
// 无法输入时阻塞
chin <- 1
fmt.Println("input sleep")
time.Sleep(time.Second)
chin <- 2
}(ch)
go func(chout <-chan int) {
fmt.Println("output sleep")
time.Sleep(time.Second)
fmt.Println("ch[1]", <-chout)
// 无法获取时阻塞,获取成功返回(value, true)
v, ok := <-chout
fmt.Println("ch[2]", v, ok)
}(ch)
time.Sleep(time.Second * 3)
var chin chan<- int = ch
close(chin)
// 关闭后返回(0, false)
x, ok := <-ch
fmt.Println(x, ok)
}
D:\gopath\src\mygo>go run main.go
output sleep
clock: 1
clock: 2
clock: 3
ch[1] 1
input sleep
clock: 4
clock: 5
clock: 6
ch[2] 2 true
clock: 7
clock: 8
clock: 9
0 false
interface TODO
整数字面值为int类型(实际上取值范围是int64),小数字面值为float64类型。
func
可变长度参数
// 这个函数可以传入任意数量的整型参数
func sum(nums ...int) {
fmt.Print(nums, " ")
total := 0
for _, num := range nums {
total += num
}
fmt.Println(total)
}
func main() {
// 支持可变长参数的函数
sum(1)
sum(1, 2, 3)
// 把切片打散传入
nums := []int{1, 2, 3, 4}
sum(nums...)
}
D:\gopath\src\mygo>go run main.go
[1] 1
[1 2 3] 6
[1 2 3 4] 10
函数对象,函数柯里化,参数函数
type IntSlice []int
func (base IntSlice) Map(f func(x int) int) (slice IntSlice) {
slice = make(IntSlice, len(base))
for i, v := range base {
slice[i] = f(v)
}
return
}
func main() {
// 函数对象
pow := func(x, y int) (ans int) {
ans = 1
for y > 0 {
y--
ans *= x
}
return
}
// 函数柯里化
powBaseX := func(x int) func(y int) int {
return func(y int) int {
return pow(x, y)
}
}
// 作为参数的函数
fmt.Println(IntSlice([]int{1, 2, 3}).Map(powBaseX(2)))
}
D:\gopath\src\mygo>go run main.go
[2 4 8]