go 基本语法
变量
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]
常用的字符串函数