Go语言在线运行
Lightly go在线运行代码的比较好的工具
mac 上配置国内镜像
export GO111MODULE=on
export GOPROXY=https://goproxy.cn
go语言常量配置
package main
import "fmt"
func consts() {
const filename string= 'abc.txt'
const a,b int= 3,4
var c int
c = int(math.Sqrt(a*a + b*b))
fmt.Println(filename,c)
}
// 普通枚举类型
func enus() {
const(
cpp =0
java = 1
python = 2
golang = 3
)
fmt.Println(cpp,java,python,golang)
}
//自增型枚举类型
func enus() {
const(
cpp =iota
java
python
golang
)
const (
b = 1 << (10 * iota)
kb
mb
gb
tb
pd
)
fmt.Println(cpp,java,python,golang)
}
func main() {
fmt.Println("Hello, World!")
enus()
}
常量也可以定义在函数外面,也就是包内部,
2-4 条件语句
package main
import "io/ioutil"
import "fmt"
func main() {
const filename = "abc.txt"
//:= 的意思是声明变量并赋值
contents,err := ioutil.ReadFile(filename)
if err != nil {
fmt.Println(err)
} else {
fmt.Printf("%s\n",contents)
}
}
- if 的条件里可以赋值
- if 条件里赋值的变量的作用域就在这个if 语句里
switch
switch 的case 条件会自动break,除非使用fallthrough
package main
import "fmt"
func grade(score int) string{
g := ""
switch {
case score <60 :
g = "F"
case score < 80 :
g = "G"
fallthrough
case score < 100:
g = "H"
default:
panic(fmt.Sprintf("Wrong score:%d",score))
}
return g
}
func main() {
fmt.Println(grade(62))
}
函数
package main
import "fmt"
func div(a,b int)(q,r int) {
q=a/b
r = a%b
return
}
func main() {
a,b := div (13,3)
fmt.Println(a,b)
}
定义函数的时候可以使用q,r 的这种用法
调用div 函数的时候会返回两个值,如果第二个不想要,可以使用_ 来表示我们不想要另一个参数的值,代码下图所示:
package main
import "fmt"
func div(a,b int)(q,r int) {
q=a/b
r = a%b
return
}
func main() {
a,_ := div (13,3)
fmt.Println(a,b)
}
可变参数列表
func sumArgs(values ...int) {
sum:=0;
for i:=range values{
sum+=values[i]
}
return sum
}
指针
var a int = 2
var pa *int = &a
*pa = 3
fmt.Println(a)
int 代表前面的这个pa变量存储的是一个int类型的带指针,所以说这个int,和int 都是对他前面变量的一个声明。
go语言的指针不能运算,不像c语言可以对头指针做加法
go语言只有值传递一种方式
func swap(a,b *int) {
*b,*a = *a,*b
}
swap(&a,&b);
传递这种对象的参数的时候也是这样的,这个对象的参数里面是包含指针的,所以你这个方法中传递对象进去,对对象进行了一些值的修改,最终也会改到外面的对象的值里去,php好像也是这个用法。
数组
package main
import "fmt"
func main() {
var arr1 [5]int
arr2 := [3]int{1,3,5}
//[...] 好像是切片的用法,这个课讲到这里是为了省去前面定义数字的麻烦。
arr3 := [...]int{2,4,6,8,10}
var grid [4][5]int
fmt.Println(arr1,arr2,arr3)
fmt.Println(grid)
//for i:=0;i<len(arr3);i++ {
// fmt.Println(arr3[i])
//}
// 上面的循环还可以写成
for i := range arr3 {
fmt.Println(arr3[i])
}
//
for i,v := range arr3 {
fmt.Println(i,v)
}
}
切片
s := arr[2:6]
s 的值为[2,3,4,5]
package main
import "fmt"
func main() {
arr:= [...]int{0,1,2,3,4,5,6,7}
fmt.Println("arr[2:6]",arr[2,6])
fmt.Println("arr[:6]",arr[:6])
fmt.Println("arr[2:]",arr[2:])
fmt.Println("arr[:]",arr[:])
}
slice 底层没有数据,而是对底层array 的一个view
slice 的拓展
package main
import "fmt"
func main() {
arr := [...]int{0,1,2,3,4,5,6,7}
s1 := arr[2:6]
s2 := s1[3:5]
//[3:5]中的这个5 如果超过数组长度,那么是会报错的
fmt.Println(s1,s2)
}
slice 中装着这三个变量,好像是使用cap的这个变量就能实现拓展。
- ptr 指向slice 开头的元素
- len 声明我这个slice 的长度是多少,用方括号取值的时候只能取到len 里面的值。
- slice 可以向后拓展,但是不能向前拓展
package main
import "fmt"
func main() {
arr := [...]int{0,1,2,3,4,5,6,7}
s1 := arr[2:6]
s2 := s1[3:5]
//[3:5]中的这个5 如果超过数组长度,那么是会报错的,也就是下面例子中的cap()方法算出来的长度,不能超过,超过就会报错。
fmt.Println(s1,s2)
}
package main
import "fmt"
func main() {
arr := [...]int{0,1,2,3,4,5,6,7}
s1 := arr[2:6]
s2 := s1[3:5]
fmt.Printf("s1 = %v,len(s1)=%d,cap(s1)=%d \n",s1,len(s1),cap(s1))
fmt.Printf("s2 = %v,len(s2)=%d,cap(s2)=%d \n",s2,len(s2),cap(s2))
}
执行结果是:
向slice 添加元素
package main
import "fmt"
func main() {
arr := [...]int{1,2,3,4,5,6,7}
s1 := arr[2:6]
//3,4,5,6,7
s2 := s1[3:5]
//6,7
s3 := append(s2,10)
//6,7,10
s4 := append(s3,11)
//6,7,10,11
s5 := append(s4,12)
//6,7,10,12
}
添加元素的时候如果超过cap,系统会重新分配更大的底层数组
go 有一个内建的函数可以去建立一个slice,
比如我们要建立一个长度为16 的一个slice
s2 := make([]int,16)
s3 := make([]int,10,32)
//这个32 是代表的一种拓展
3-3 切片的操作
package main
import "fmt"
func printSlice(s []int) {
fmt.Printf("%v , len = %d,cap = %d,\n",s,len(s),cap(s))
}
func main() {
fmt.Println("creating slice")
var s []int //zero value is nil
for i:=0 ;i<100;i++ {
//printSlice(s)
s = append(s,2*i+1)
}
fmt.Println(s)
s1 := []int{2,4,6,8}
printSlice(s1)
s2 := make([]int,16)
s3 := make([]int,16,32)
printSlice(s2)
printSlice(s3)
fmt.Println("coping slice")
copy(s2,s1)
printSlice(s2)
fmt.Println("deleting element from slice")
fmt.Println(s2[:3])
//数学中能取到的数,叫做闭,取不到这个数叫做 开,
//那么s2 的值是 [2 4 6 8 0 0 0 0 0 0 0 0 0 0 0 0]
//s2[:3] 就要从元素0开始数,数到3,数到3之后给开掉,[:3],就是一种前闭后开的模式
//所以 s2[:4]的值是[2 4 6] 不包括第三位的元素 8
//而下面的s2[4:] 是包括第四位数字0的
fmt.Println(s2[4:])
//这里采用的是一种拼接的方式,想要加入s2[4:]后面的所有元素,
//那么就需要在s2[4:]后面加三个点
s2 = append(s2[:3],s2[4:]...)
fmt.Println(s2)
fmt.Println("Poping from front")
front := s2[0]
fmt.Println(front)
s2= s2[1:]
fmt.Println("poping from back")
tail := s2[len(s2)-1]
//s2 := s2[:len(s2)-1]
fmt.Println(tail)
printSlice(s2)
}
3-4 Map
go语言在线运行
package main
import "fmt"
func main() {
m := map[string]string{
"name":"ccoouse",
"course":"golang",
"site":"imooc",
"quality":"notbad",
}
//
m2 := make(map[string]int)
var m3 map[string]int
fmt.Println(m,m2,m3)
fmt.Println("Traversing map")
for k,v := range m {
fmt.Println(k,v)
}
fmt.Println("Getting values")
courseName, ok := m["course"]
//当这个m["course"] 打错了的时候,下面会输出空白的一行
fmt.Println(courseName,ok)
if courseName, ok := m["cours"];ok {
fmt.Println(courseName)
} else {
fmt.Println("key does not exist")
}
fmt.Println("Deleting values")
name,ok := m["name"]
fmt.Println(name,ok)
delete(m,"name")
name,ok = m["name"]
fmt.Println(name,ok)
}
创建map 使用 make(map[string]int)
获取元素:m[key]
key 不存在的时候,获得value类型的初始值
用value,ok:= m[key] 来判断是否存在key
delete 可以删除一个key
map 的遍历
使用range遍历key,或者遍历key,value 对
不保证遍历顺序,如需顺序,需手动对key排序
使用len 获得元素个数。
map 的key
map 使用哈希表,必须可以比较相等。
除了slice,map,function 的内建类型都可以作为key
struct 类型不包含上述字段,也可作为key
map 例题
寻找最长的不含有重复字符的子串
package main
import "fmt"
func lengthOfNonRepeatingSubStr(s string) int {
lastOccurred := make(map[byte]int)
start := 0
maxLength := 0
for i,ch := range []byte(s) {
if lastI,ok :=lastOccurred[ch];ok&&lastI >= start {
start = lastOccurred[ch] +1
}
if i-start +1 > maxLength {
maxLength = i-start +1
}
lastOccurred[ch] = i
}
return maxLength
}
func main() {
fmt.Println(lengthOfNonRepeatingSubStr("abcabcbb"))
fmt.Println(lengthOfNonRepeatingSubStr("bbbb"))
}
3-6 字符和字符串处理
package main
4-3 包和封装
每个目录一个包
main包包含可执行入口,
为结构定义的方法,必须放到同一个包内。
可以是不同的文件,
参考资料 3、go的package介绍和使用
5-1 依赖管理
8-4 gin框架的github地址
还有一个是写日志的包 zap,github的地址是
参考资料: