[TOC]
常见数据类型
值类型
值类型:基本数据类型int、float、bool、string、数组和结构体struct都属于值类型,使用这些类型的变量是直接使用指向存在内存中的值,值类型的变量的值通常存储在栈中
引用类型
引用类型:指针、slice切片、map、管道chan、interface等都是引用类型
字符串
golang的统一编码为utf-8,golang中string底层是通过byte数组实现的。中文字符在unicode下占2个字节,在utf-8编码下占3个字节,而golang默认编码正好是utf-8,所以字母数字占一字节,汉字占3字节
要获取一个字符串的长度,有以下2种方式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| package main
import ( "fmt" "unicode/utf8" )
func main() { str := "hello 芝麻开门" fmt.Println("str 的长度:", len(str))
fmt.Println("str 的RuneCountInString长度:", utf8.RuneCountInString(str)) fmt.Println("str 的rune convert长度:", len([]rune(str)))
}
|
golang中还有一个byte数据类型,与rune相似,它们都是用来表示字符类型的变量类型。它们的不同在于:
- byte 等同于int8,常用来处理ascii字符
- rune 等同于int32,常用来处理unicode或utf-8字符
- 循环一个字符串时,如果有中文,需要转切片,不然会出现乱码,因为是按照字符串的字节长度遍历
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
| package main
import ( "fmt" "unicode/utf8" )
func main() { str := "hello 芝麻开门" fmt.Println("str 的长度:", len(str))
fmt.Println("str 的RuneCountInString长度:", utf8.RuneCountInString(str)) fmt.Println("str 的rune convert长度:", len([]rune(str)))
runeStr := []rune(str) for i := 0; i < len(runeStr); i++ { fmt.Printf("%c\n", runeStr[i]) }
fmt.Println(strings.Contains("hello world", "hello"))
fmt.Println(strings.Count("hello world", "o"))
fmt.Println(strings.EqualFold("hello world", "Hello World"))
fmt.Println(strings.Index("hello world", "o"))
fmt.Println(strings.LastIndex("hello world", "o"))
fmt.Println(strings.Replace("hello world", "hello", "你好", 1))
strArr := strings.Split("hello world", "o w") fmt.Printf("strArr 类型 %T,值%v\n", strArr, strArr) for i := 0; i < len(strArr); i++ { fmt.Println(strArr[i])
}
fmt.Println(strings.ToLower("HELLO WORLD")) fmt.Println(strings.ToUpper("hello world"))
fmt.Println(strings.TrimRight("~hello world~", "~")) fmt.Println(strings.TrimLeft("~hello world~", "~")) fmt.Println(strings.Trim("~hello world~", "~"))
fmt.Println(strings.HasPrefix("hello world", "hello")) fmt.Println(strings.HasSuffix("hello world", "hello"))
fmt.Println(strings.Join(strArr, "o w"))
fmt.Println(strings.Repeat("go ", 3)) }
|
数组
声明数组
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| func arrayDemo() { var arr [3]int = [3]int{1, 2, 3} arr1 := [3]int{1, 2, 3} fmt.Println(arr, arr1)
arr2 := [...]int{5: -1} fmt.Println(arr2)
var arr3 [3]int fmt.Println(arr3)
arr4 := [3][2]int{} arr5 := [3][2]string{{"a", "b"}, {"AA", "BB"}, {"AAA", "BBB"}} fmt.Println(arr4, arr5)
arr6 := new([3]int) fmt.Printf("arr6类型%T,值%v", arr6, arr6)
arr7 := new([2]int) fmt.Printf("arr7类型%T,值%v" , arr7 , arr7) }
|
遍历数组
1 2 3 4 5 6 7
| func for_range() { arr := [...]string{"go", "php", "java"} for key, value := range arr { fmt.Printf("key = %v , value = %v", key, value) } }
|
slice切片
定义和创建
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| package main
import "fmt"
func main() { sliceDemo1() sliceDemo2() sliceDemo3() } func sliceDemo1() { var arr [5]int = [...]int{1, 2, 3, 4, 5} var slice = arr[1:3] // slice value=[2 3] , cap=4 , len=2 fmt.Printf("slice value=%v , cap=%v , len=%v", slice, cap(slice), len(slice)) } func sliceDemo2() { var slice []int = make([]int, 5, 10) fmt.Println(slice) // [0 0 0 0 0] slice[1] = 5 slice[3] = 10 // slice value=[0 5 0 10 0] , cap=10 , len=5 fmt.Printf("slice value=%v , cap=%v , len=%v", slice, cap(slice), len(slice)) } func sliceDemo3() { // 声明和初始化一个切片 var slice []string = []string{"hello", "world", "!"} fmt.Printf("slice value=%v , cap=%v , len=%v", slice, cap(slice), len(slice)) }
|
三种方式说明及区别
说明
sliceDemo1:让切片引用一个已经存在的数组创建切片
sliceDemo2:使用make来创建,可以指定切片的大小和容量,如果没有给切片赋值,则会使用默认值,(int、float=>0, strint=>””, bool=>false);make方式创建的切片对应的数组由make底层维护,对外不开见,只能通过slice访问各个元素
sliceDemo3:定义一个切片直接指定具体数组
区别
sliceDemo1方式是直接引用数组,这个数组是事先存在的,对程序员可见
sliceDemo2通过make创建切片,make也会创建一个数组,是由切片在底层维护,该数组对程序员不可见
冒泡排序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
| package main
import "fmt"
func main() { arr := [8]int{22, 31, 23, 44, 1, 55, 54, 33}
fmt.Println(bubble1(arr)) fmt.Println(bubble2(arr)) fmt.Println(bubble3(arr)) } func bubble1(data [8]int) [8] int { for i := 0; i < len(data)-1; i++ { fmt.Println(data[i]) for j := 0; j < len(data)-1-i; j++ { if data[j] > data[j+1] { tmp := data[j] data[j] = data[j+1] data[j+1] = tmp } } } return data }
func bubble2(data [8]int) [8]int { for i := 0; i < len(data); i++ { for j := i + 1; j < len(data); j++ { if data[i] > data[j] { tmp := data[i] data[i] = data[j] data[j] = tmp } } } return data } func bubble3(data [8]int) [8]int { for i := 0; i < len(data); i++ { for j := 0; j < len(data)-1; j++ { if data[j] > data[j+1] { tmp := data[j] data[j] = data[j+1] data[j+1] = tmp } } } return data }
|
map
map相当于PHP中的关联数组
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| package main
import "fmt"
func main() { mapDemo() } func mapDemo() { var map1 map[string]string map1 = make(map[string]string, 5) map1["name"] = "zhimma" map1["address"] = "xian" fmt.Println(map1)
map2 := make(map[string]string) map2["name"] = "zhimma" map2["address"] = "xian" fmt.Println(map2)
map3 := map[string]string{ "name": "zhimma", "address": "xian", } fmt.Println(map3) }
|
指针相关概念
变量:变量是基本类型,变量存的就是值,也叫值类型
地址:用于引用计算机的内存地址,可理解为内存地址的标签,通俗一点讲就是一个房子在小区门牌号
1 2 3 4 5 6 7 8 9 10
| package main
import "fmt"
func main() { name := "zhimma" fmt.Println("name 的地址是", &name) }
|
指针:指针变量存的是一个地址,这个地址指向的空间存的才是值,指针是一个指向另一个变量内存地址的值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| package main
import "fmt"
func main() { var i int = 1 fmt.Println("i 的地址是", &i)
var ptr *int = &i fmt.Printf("ptr=%v\n", ptr) fmt.Printf("ptr的地址是%v\n", &ptr) fmt.Printf("ptr指向的值是%v\n", *ptr)
}
|
&:取地址符,指针 := &变量
*:取值符, 变量 := *指针
匿名函数
定义匿名函数有2种方式
定义时直接使用(这种方式只使用一次)
1 2 3 4 5 6 7 8 9 10
| package main
import "fmt"
func main() { totalNum := func(a int, b int) int { return a + b }(5, 3) fmt.Println(totalNum) }
|
将匿名函数赋值给变量
1 2 3 4 5 6 7 8 9 10 11 12
| package main
import "fmt"
func main() { sumFunc := func(a int, b int) int { return a + b } total := sumFunc(1, 2) fmt.Println(total) }
|
全局匿名函数
1 2 3 4 5 6 7 8 9 10 11 12
| package main
import "fmt"
var globalFunc = func(params string) string { return "this is globalFunc and receive params str is'" + params + "'" }
func main() { str := globalFunc("hello world") fmt.Println(str) }
|
闭包
new函数
new函数用来分配内存,主要分配值类型,比如int、float32、struct等,返回的是指针
1 2 3 4 5 6 7 8 9 10 11
| func newDemo() { num := 100 fmt.Printf("num 的类型是%T,值是%v,地址是%v", num, num, &num)
num1 := new(int) fmt.Printf("num1 的类型是%T,值是%v,地址是%v", num1, num1, &num1) fmt.Printf("num1 的类型是%T,值是%v,地址是%v,指向的值是%v", num1, num1, &num1, *num1) }
|