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]
常用的字符串函数

posted @ 2020-02-29 20:58  simp00  阅读(256)  评论(0编辑  收藏  举报