变量
var声明
// Go语言中推荐使用驼峰式命名 // var student_name string var studentName string // var StudentName string // 声明变量 // var name string // var age int // var isOk bool // 批量声明 var ( name string // "" age int // 0 isOk bool // false ) func main() { name = "理想" age = 16 isOk = true // var heiheihei string // Go语言中非全局变量声明后必须使用,不使用就编译不过去 fmt.Print(isOk) // 在终端中输出要打印的内容 fmt.Println() fmt.Printf("name:%s\n", name) // %s:占位符 使用name这个变量的值去替换占位符 fmt.Println(age) // 打印完指定的内容之后会在后面加一个换行符 // heiheihei = "嘿嘿嘿" // 声明变量同时赋值 var s1 string = "whb" fmt.Println(s1) // 类型推导(根据值判断该变量是什么类型) var s2 = "20" fmt.Println(s2) // 简短变量声明,只能在函数里面用 s3 := "哈哈哈" fmt.Println(s3) // s1 := "10" // 同一个作用域({})中不能重复声明同名的变量 // 匿名变量是一个特殊的变量:_(后面学了函数再说) }
const
// 常量 // 定义了常量之后不能修改 // 在程序运行期间不会改变的量 const pi = 3.1415926 // 批量声明常量 const ( statusOK = 200 notFound = 404 ) // 批量声明常量时,如果某一行声明后没有赋值,默认就和上一行一致 const ( n1 = 100 n2 n3 ) // iota const ( a1 = iota // 0 a2 // 1 a3 // 2 ) const ( b1 = iota // 0 b2 = iota // 1 _ = iota // 2 b3 = iota // 3 ) // 插队 const ( c1 = iota // 0 c2 = 100 // 100 c3 = iota // 2 c4 ) // 多个常量声明在一行 const ( d1, d2 = iota + 1, iota + 2 // d1:1 d2:2 d3, d4 = iota + 1, iota + 2 // d3:2 d4:3 ) // 定义数量级 const ( _ = iota KB = 1 << (10 * iota) MB = 1 << (10 * iota) GB = 1 << (10 * iota) TB = 1 << (10 * iota) PB = 1 << (10 * iota) ) func main() { // pi = 123 // fmt.Println("n1:", n1) // fmt.Println("n2:", n2) // fmt.Println("n3:", n3) // fmt.Println("a1:", a1) // fmt.Println("a2:", a2) // fmt.Println("a3:", a3) // fmt.Println("b1:", b1) // fmt.Println("b2:", b2) // fmt.Println("b3:", b3) // fmt.Println("c1:", c1) // fmt.Println("c2:", c2) // fmt.Println("c3:", c3) // fmt.Println("c4:", c4) fmt.Println("d1:", d1) fmt.Println("d2:", d2) fmt.Println("d3:", d3) fmt.Println("d4:", d4) }
int
// 整型 func main() { // 十进制 var i1 = 101 fmt.Printf("%d\n", i1) fmt.Printf("%b\n", i1) // 把十进制数转换成二进制 fmt.Printf("%o\n", i1) // 把十进制数转换成八进制 fmt.Printf("%x\n", i1) // 把十进制数转换成十六进制 // 八进制 i2 := 077 fmt.Printf("%d\n", i2) // 十六进制 i3 := 0x1234567 fmt.Printf("%d\n", i3) // 查看变量的类型 fmt.Printf("%T\n", i3) // 声明int8类型的变量 i4 := int8(9) // 明确指定int8类型,否则就是默认为int类型 fmt.Printf("%T\n", i4) }
float
package main import "fmt" // 浮点数 func main() { // math.MaxFloat32 // float32最大值 f1 := 1.23456 fmt.Printf("%T\n", f1) // 默认Go语言中的小数都是float64类型 f2 := float32(1.23456) fmt.Printf("%T\n", f2) // 显示声明float32类型 // f1 = f2 // float32类型的值不能直接复赋值给float64类型的变量 }
bool
package main import "fmt" // 布尔值 func main() { b1 := true var b2 bool // 默认是false fmt.Printf("%T\n", b1) fmt.Printf("%T value:%v\n", b2, b2) }
fmt
package main import "fmt" // fmt占位符 func main() { var n = 100 // 查看类型 fmt.Printf("%T\n", n) fmt.Printf("%v\n", n) fmt.Printf("%b\n", n) fmt.Printf("%d\n", n) fmt.Printf("%o\n", n) fmt.Printf("%x\n", n) var s = "Hello 沙河!" fmt.Printf("字符串:%s\n", s) fmt.Printf("字符串:%v\n", s) fmt.Printf("字符串:%#v\n", s) }
string
package main import ( "fmt" "strings" ) // 字符串 func main() { // \ 本来是具有特殊含义的,我应该告诉程序我写的\就是一个单纯的\ path := "'D:\\Go\\src\\code.oldboyedu.com\\studygo\\day01'" fmt.Println(path) s := "I'm ok" fmt.Println(s) // 多行的字符串 s2 := ` 世情薄 人情恶 雨送黄昏花易落 ` fmt.Println(s2) s3 := `D:\Go\src\code.oldboyedu.com\studygo\day01` fmt.Println(s3) // 字符串相关操作 fmt.Println(len(s3)) // ? // 字符串拼接 name := "理想" world := "大帅比" ss := name + world fmt.Println(ss) ss1 := fmt.Sprintf("%s%s", name, world) // fmt.Printf("%s%s", name, world) fmt.Println(ss1) // 分隔 ret := strings.Split(s3, "\\") fmt.Println(ret) // 包含 fmt.Println(strings.Contains(ss, "理性")) fmt.Println(strings.Contains(ss, "理想")) // 前缀 fmt.Println(strings.HasPrefix(ss, "理想")) // 后缀 fmt.Println(strings.HasSuffix(ss, "理想")) s4 := "abcdeb" fmt.Println(strings.Index(s4, "c")) fmt.Println(strings.LastIndex(s4, "b")) // 拼接 fmt.Println(strings.Join(ret, "+")) }
byte
package main import "fmt" // byte和rune类型 // Go语言中为了处理非ASCII码类型的字符 定义了新的rune类型 func main() { s := "Hello沙河사샤" // len()求得是byte字节的数量 n := len(s) // 求字符串s的长度,把长度保存到变量n中 fmt.Println(n) // for i := 0; i < len(s); i++ { // // fmt.Println(s[i]) // fmt.Printf("%c\n", s[i]) // %c:字符 // } // for _, c := range s { // 从字符串中拿出具体的字符 // fmt.Printf("%c\n", c) // %c:字符 // } // "Hello" => 'H' 'e' 'l' 'l' 'o' // 字符串修改 s2 := "白萝卜" // => '白' '萝' '卜' s3 := []rune(s2) // 把字符串强制转换成了一个rune切片 s3[0] = '红' fmt.Println(string(s3)) // 把rune切片强制转换成字符串 c1 := "红" c2 := '红' // rune(int32) fmt.Printf("c1:%T c2:%T\n", c1, c2) c3 := "H" // string c4 := byte('H') // byte(uint8) fmt.Printf("c3:%T c4:%T\n", c3, c4) fmt.Printf("%d\n", c4) // 类型转换 n1 := 10 // int var f float64 f = float64(n1) fmt.Println(f) fmt.Printf("%T\n", f) }
基本程序结构
条件和循环
if
package main import "fmt" // if条件判断 func main() { // age := 19 // if age > 18 { // 如果 age > 18 就执行这个{}中的代码 // fmt.Println("澳门首家线上赌场开业啦!") // } else { // 否则就执行这个{}中的代码 // fmt.Println("改写暑假作业啦!") // } // 多个判断条件 // if age > 35 { // fmt.Println("人到中年") // } else if age > 18 { // fmt.Println("青年") // } else { // fmt.Println("好好学习!") // } // 作用域 // age变量此时只在if条件判断语句中生效 if age := 19; age > 18 { // 如果 age > 18 就执行这个{}中的代码 fmt.Println("澳门首家线上赌场开业啦!") } else { // 否则就执行这个{}中的代码 fmt.Println("改写暑假作业啦!") } // fmt.Println(age) // 在这里是找不到age }
n:=0 for n<5{ n++ fmt.Println(n) }
无限循环
n:=0 for{ n++ fmt.Println(n) }
switch与其它语言的区别
1.条件表达式不限制为常量或者证书;
2.单个case中,可以出现多个结果选项,使用逗号分隔;
3.与C语言等规则相反,go语言不需要用break来明确退出一个case;
4.可以不设定 switch之后的条件表达式,在此种情况下,整个switch结构与多个if else 的逻辑作用相同
func TestSwitchMultiCase(t *testing.T){ for i:=0;i<5;i++{ switch i { case 0, 2: t.Log("Even") case 1,3: t.Log("Odd") default: t.Log("it is not 0-3") } } } func TestSwitchCaseCondition(t*testing.T){ for i:=0;i<5;i++{ switch { case i%2==0: t.Log("Even") case i%2==1: t.Log("Odd") default: t.Log("unknown") } }
常用集合
数组和切片
var a [3]int//声明并初始化为默认值0 a[0]=1 b:=[3]int{1,2,3}//声明同时初始化 c:=[2][2]int{{1,2},{3,4}}//多维数组初始化
数组的初始化与遍历
import "testing" func TestArrayInit(t *testing.T){ var arr[3]int//初始化默认结果为0 arr1:=[4]int{1,2,3,4}// arr2:=[...]int{1,3,4,5} t.Log(arr[1],arr[2]) t.Log(arr1[1],arr2[1]) } func TestArrayTravel(t *testing.T){ arr3 := [...]int{1,2,3,4,5} for i:=0;i<len(arr3);i++{ t.Log(arr3[i]) } for idx,e:=range arr3{ t.Log(idx,e) } }
数组截取
a[开始索引(包含),结束索引(不包含)]
a:=[...]int{1,2,3,4,5,60}
a[1:2]//2
a[1:3]//2,3
a[1:len(a)]//2 3 4 5
a[1:]//2,3,4,5,60
a[:3]//1,2,3
切片内部结构
切片内部是一个结构体
func TestSliceGrowing(t *testing.T){ s:=[]int{} for i:=0;i<10;i++{ s = append(s, i) t.Log(len(s),cap(s)) } }
=== RUN TestSliceGrowing --- PASS: TestSliceGrowing (0.00s) slice_test.go:24: 1 1 slice_test.go:24: 2 2 slice_test.go:24: 3 4 slice_test.go:24: 4 4 slice_test.go:24: 5 8 slice_test.go:24: 6 8 slice_test.go:24: 7 8 slice_test.go:24: 8 8 slice_test.go:24: 9 16 slice_test.go:24: 10 16 PASS
共享连续存储控件
func TestSliceShareMemory(t *testing.T){ year:=[]string{"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"} Q2:=year[3:6] t.Log(Q2,len(Q2),cap(Q2)) summer :=year[5:8] t.Log(summer,len(summer),cap(summer)) }
=== RUN TestSliceShareMemory --- PASS: TestSliceShareMemory (0.00s) slice_test.go:30: [Apr May Jun] 3 9 slice_test.go:32: [Jun Jul Aug] 3 7 PASS
数组 vs 切片
1.容量是否可伸缩
数组不可伸缩
2.是否可以进行比较
数组长度相同可以比较,slice 只能与nil进行比较 不可以比较两个slice
Map声明 元素访问及遍历
m:=map[string]int{"one":1,"two":2,"three":3}
m1:=map[string]int{}
m1["one"]=1
m2:=make(map[string]int, 10/Initial Capacity/)//为什么不初始化len?
判断map里面的值是否存在
func TestAccessNotExistingKey(t *testing.T){ m1:=map[int]int{} t.Log(m1[1]) m1[2]=0 t.Log(m1[2]) m1[3]=0 if v,ok:=m1[3];ok{ t.Log("key 3 is ",v) }else{ t.Log("key 3 is not existing") } }
map 元素的访问
与其他主要编程语言的差异
在访问key不存在时, 仍然会返回零值,不能通过返回nil来判断元素是否存在
if v,ok:=m["four"];ok{ t.log("four",v) } else{ t.Log("Not existing") }
map元素的遍历
m:=map[string]int{"one":1,"two":2,"three":3} for k,v :range m{ t.Log(k,v) } func TestTravelMap(t*testing.T){ m:=map[string]int{"one":1,"two":2,"three":3} for k,v:=range m{ t.Log(k,v) } }
Map 与工厂模式,在go语言中实现工厂模式
map与工厂模式
- Map的value可以是一个方法
- 与Go的Dock type接口方式一起,可以方便的实现单一方法对象的工厂模式
//value是一个方法 package _map import "testing" func TestMapWithFunVlaue(t *testing.T){ m:=map[int]func(op int)int{} 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*op} t.Log(m[1](2),m[2](2),m[3](2)) }
实现Set
Go的内置集合中没有set实现,可以map[type]bool
1.元素的唯一性
2.基本操作
- 添加元素
- 判断元素是否存在
- 删除元素
- 元素个数
func TestMapForSet(t*testing.T){ mySet:=map[int]bool{} mySet[1]=true n:=1 if mySet[n]{ t.Logf("%d is existing",n) }else{ t.Logf("%d is not existing",n) } mySet[3]=true delete(mySet,1) n=1 if mySet[n]{ t.Logf("%d is existing",n) }else{ t.Logf("%d is not existing",n) } }
字符串
与其它主要编成语言的差异
1.string 是数据类型,不是引用类型或者指针类型
2.string是只读的byte slice len函数可以计算它所包含的byte数
3.string的byte数组可以存放任何数据
Unicode 与UTF8
1.Unicode是一种字符集(code point)
2.UTF8是unicode的存储实现(转换为字节序列的规则)
编码与存储
字符 "中"
Unicode 0x4E2D
UTF-8 0xE4B8AD
string/[]byte [0xE4,0xB8,0xAD]
常用的字符串函数