概覽
下載
開發: vi emacs idea eclipse vs sublime
Ide: GoLand,liteIDE
默認 gopath ~/go/src
基本語法
變量定義使用 var,函數外定義可以使用括號的方式
package main
import "fmt"
//函數外定義要使用var
var aa=3
var ss="kkk"
var bb =true
//可以使用括號的方式
var (
cc int
dd string
ee bool
)
func variableZeroValue() {
var a int
var s string
fmt.Println("%d %qn", a, s)
}
func variableInitialValue() {
var a, b int = 3, 4
var s string = "abc"
fmt.Println(a, b, s)
}
func variableTypeDedtection() {
var a, b, c, s = 2, 3, true, "def"
// 類型推斷
fmt.Println(a, b, c, s)
}
//冒號定義
func variableShorter() {
//第一次
a, b, c, s := 2, 3, true, "def"
// 類型推斷
fmt.Println(a, b, c, s)
}
func main() {
fmt.Println("hello world")
variableZeroValue()
variableInitialValue()
variableTypeDedtection()
variableShorter()
}
內建類型
boolstring(u)int(u)int8(u)int16(u)int32(u)int64uintptr(指針)byte,rune(字符 go 的 char 類型,32 位)float32,float64,complex64,complex128(complex 複數類型,實部虛部)
複數回顧
- i = $sqrt{-1}$
- 複數:3+4i
- $|x+y|$ 的模 = $sqrt{3^2+4^2}$ = 5
- $i^2$=-1,$i^3$=-i,$i^4$=1,...
- $e^{iphi}$ = cos$phi$+isin$phi$
e 是單位圓,$phi$是逆時針旋轉的角度,如圖 (泰勒極數展開)
- $e^{iphi}$ = $sqrt{cos^2phi+sin^2phi}$ = 1
- $e^{ipi}$ = -1, $e^{ifrac{3}{2}pi}$ = -i,$e^{i2pi}$=1
- 推導出歐拉公式 $e^{ipi}$+1=0
go 語法來驗證
func euler(){
c:= 3+4i //表示複數
fmt.Println(cmplx.Abs(c))
//歐拉公式
fmt.Println(cmplx.Pow(math.E,1i*math.Pi)+1)
fmt.Println(cmplx.Exp(1i*math.Pi)+1)
}
強制類型轉換
go 只有強制類型轉換
func triangle() {
var a, b int = 3, 4
var c int
c = int(math.Sqrt(float64(a*a + b*b)))
fmt.Println(c)
}
常量定義
func consts() {
const filename = "abc.txt"
const a, b = 3, 4
var c int
c = int(math.Sqrt(float64(a*a + b*b)))
fmt.Println(filename, c)
}
枚舉類型
- 普通枚舉類型
- 自增值枚舉類型
func enums() {
const (
cpp = 0 //iota const是自增值
java = 1
python = 2
gloang = 3
)
// b,kb,mb,gb,tb,pb
const (
b = 1 << (10 * iota)
kb
mb
gb
tb
pb
)
}
回顧
- 變量類型寫在變量之後
- 編譯器可推測變量類型
- 沒有 char,只有 rune
- 原生支持複數類型
if
// 不需要括號的
package main
import (
"fmt"
"io/ioutil"
)
func main() {
const filename = "abc.txt"
contents,err:=ioutil.ReadFile(filename)
if err!=nil {
fmt.Println(err)
} else {
fmt.Printf("%sn",contents)
}
}
// 或者條件之前先賦個值用分號分隔
func main() {
const filename = "abc.txt"
//contents,err:=ioutil.ReadFile(filename)
if contents,err:=ioutil.ReadFile(filename); err!=nil {
fmt.Println(err)
} else {
fmt.Printf("%sn",contents)
}
}
switch
// switch 沒有break;
func switchFunc(a, b int, op string) int {
var result int
switch op {
case "+":
result = a + b
case "-":
result = a - b
case "*":
result = a * b
case "/":
if b == 0 {
fmt.Printf("%sn", errors.New("除數為零"))
break
}
result = a / b
default:
fmt.Printf("not found operation")
}
return result
}
// 另外一種switch不寫值,而在case中寫條件判斷
func grade(score int) string {
g := ""
switch {
case score<0 || score>100
panic(fmt.Sprintf("Wrong score: %d", score)) //中斷程序執行
case score < 60:
g = "F"
case score < 80:
g = "C"
case score < 90:
g = "B"
case score <= 100:
g = "A"
}
return g
}
switch 會自動 break,除非使用 fallthrough
for
直觀的是沒有括號
package main
import (
"fmt"
"strconv"
)
func convertToBin(n int) string {
result := ""
for ; n > 0; n /= 2 {
lsb := n % 2
result = strconv.Itoa(lsb) + result
}
return result
}
func main() {
fmt.Println(
convertToBin(5), //101
convertToBin(13), //1011--> 1101
)
// 調用時,返回值不有可以用_來點位
}
遞增條件也可以省略
func printFile(filename string) {
file, err := os.Open(filename)
if err != nil {
panic(err)
}
scanner := bufio.NewScanner(file)
for scanner.Scan() {
//相當於while
fmt.Println(scanner.Text())
}
}
//甚麼都不加就是死循環,因為併發編程時要用到gorutine
函數
函數名在前 返回值在後。返回值可以是多個值,可以給返回值取名字;通常情況下返回一個值,一個 error,函數的參數也可以是個函數,它沒有默認參數,有一個可變參數列表...
package main
import (
"fmt"
"math"
"reflect"
"runtime"
)
func main() {
//div(13, 3)
fmt.Println(apply(pow, 2, 3))
fmt.Println(apply(func(i int, i2 int) int {
return int(math.Pow(float64(i), float64(i2)))
}, 3, 4))
fmt.Println("多參數和:", sum(1, 2, 3))
}
func divid(a,b int) (int,int){
var q,r int
q = a/b
r = a%b
return q,r
}
// 多個返回值,並指定名字
func div(a, b int) (q, r int) {
q = a / b
r = a % b
return
}
func pow(a, b int) int {
return int(math.Pow(float64(a), float64(b)))
}
// 參數傳函數
func apply(op func(int, int) int, a, b int) int {
p := reflect.ValueOf(op).Pointer()
opName := runtime.FuncForPC(p).Name()
fmt.Printf("Calling function %s with args"+
"(%d,%d)n", opName, a, b)
return op(a, b) //也可以使用匿名函數
}
// 可變參數
func sum(number ...int) int {
sum := 0
for _, v := range number {
sum += v
//fmt.Println(v)
}
return sum
}
特點
- 返回值類型寫在最後面
- 可返回多個值
- 函數可作為參數
- 沒有默認參數,可變參數列表
指針
var a int=2
var pa *int = &a
*pa = 3
// 有指針,但指針不能運算
go 傳值,引用傳遞? go 語言只有值傳遞一種方式
// 沒效果
func main(){
c, d := 2, 3
fmt.Printf("c=%v,d=%vn", c, d)
swap(c, d)
fmt.Printf("nswaped c=%v,d=%vn", c, d)
}
// 值傳遞的,還是地址傳遞的說明
func swap(a, b int) {
a, b = b, a
}
// 解決一 swap參數為地址,調用時要傳地址
func main(){
c, d := 2, 3
fmt.Printf("c=%v,d=%vn", c, d)
swap(&c, &d)
fmt.Printf("nswaped c=%v,d=%vn", c, d)
}
// 值傳遞的,還是地址傳遞的說明
func swap(a, b *int) {
*a, *b = *b, *a //地址交換
}
// 解決二,返回新的數據
func swapv1(a,b int) (int,int){
return b,a
}
數組
func main() {
var arr1 [5]int
arr2:=[3]int{1,3,5}
arr3:=[...]int{2,4,6,8,10} //不寫...就是切片了
fmt.Println(arr1,arr2,arr3)
// 遍歷數據
for i := 0; i < len(arr3); i++ {
fmt.Println(arr3[i])
}
// 一般使用range來遍歷 i是下標,v是值
for i, v := range arr3 {
fmt.Println(i, v)
}
// 最大值
maxi, maxv := MaxNumber(&arr3)
fmt.Printf("nMax index %v value %vn",maxi, maxv)
arr4:=[]int{1,3,5,7,9,11}
maxi, maxv := MaxNumberv1(&arr4)
fmt.Printf("nMax index %v value %vn",maxi, maxv)
}
// 求最大值
func MaxNumber(numbers *[5]int)(int,int){
maxi:=-1
maxValue:=-1
for i,v:=range numbers {
if v>maxValue {
maxi,maxValue = i,v
}
}
}
// 求最大值
func MaxNumberv1(numbers *[]int) (int, int) {
maxi := -1
maxValue := -1
for i, v := range *numbers {
if v > maxValue {
maxi, maxValue = i, v
}
}
return maxi, maxValue
}
數組是值類型 而且必須規定長度
func printArray(arr [5]int) {
// 注意這個參數 [5]int 和 []int不是一回事兒
// 也可以*[5]int也可以傳地址
for i,v:=range arr {
fmt.Println(i,v)
}
}
// main中調用時
printArray(arr3) //對的
printArray(arr4) //會報類型錯誤
printArray(arr1) //對的
printArray(arr2) //錯的 因為長度對不上,認為是兩種類型
切片 Slice
理解為它是數組的一個視圖
package main
import "fmt"
func main() {
arr := [...]int{1, 2, 3, 4, 5, 6, 7}
s := arr[2:6]
fmt.Println("arr=", arr)
fmt.Println("arr[2:6]=", s)
fmt.Println("arr[2:]=", arr[2:])
fmt.Println("arr[:6]=", arr[:6])
fmt.Println("arr[:]=", arr[:])
s1 := arr[2:]
s2 := arr[:]
fmt.Println("s1=", s1)
fmt.Println("s2=", s2)
fmt.Println("After updateSlice(s1)")
UpdateSlices(s1)
fmt.Println(s1)
fmt.Println(arr)
fmt.Println("After updateSlice(s2)")
UpdateSlices(s2)
fmt.Println(s2)
fmt.Println(arr)
}
func UpdateSlices(s []int) {
s[0] = 100
}
/*
arr= [1 2 3 4 5 6 7]
arr[2:6]= [3 4 5 6]
arr[2:]= [3 4 5 6 7]
arr[:6]= [1 2 3 4 5 6]
arr[:]= [1 2 3 4 5 6 7]
s1= [3 4 5 6 7]
s2= [1 2 3 4 5 6 7]
After updateSlice(s1)
[100 4 5 6 7]
[1 2 100 4 5 6 7]
After updateSlice(s2)
[100 2 100 4 5 6 7]
[100 2 100 4 5 6 7]
*/
證明 slice 是數組的一個視圖,
reslice
fmt.Println("Reslice:")
s2=s2[:5]
s2=s2[2:]
fmt.Println("Reslice s2[:5] s2[2:]",s2)
s2[0] = 200
fmt.Println("arr", arr)
/*
Reslice:
Reslice s2[:5] s2[2:] [100 4 5]
arr [100 2 200 4 5 6 7]
它們都是不同的view array
*/
arr[0], arr[2] = 1, 2
s1 = arr[2:6]
s2 = s1[3:5]
fmt.Println("s1=", s1)
fmt.Println("s2=", s2)
/*
rr [100 2 200 4 5 6 7]
s1= [2 4 5 6]
s2= [6 7]
*/
為甚麼能取出這樣的值呢看下圖,slice 下標更新示意圖
只要你不超過 capicity
slice 可以向後擴展,不可以向前擴展,s[i]不可以超越len(s),向後擴展不可以超越底層數組cap(s)
arr[0], arr[2] = 1, 2
s1 = arr[2:6]
s2 = s1[3:5]
fmt.Printf("s1=%d,len(s1)=%d,cap(s1)=%vn", s1, len(s1), cap(s1))
fmt.Printf("s2=%d,len(s2)=%d,cap(s2)=%vn", s2, len(s2), cap(s2))
向 slice 中不斷的添加值
s3 := append(s2, 10)
s4 := append(s3, 11)
s5 := append(s4, 12)
fmt.Println("arr", arr)
fmt.Println("s3,s4,s5", s3, s4, s5)
s4,s5 就不是原來的 arr,系統將會分配更新長的的數組。
添加元素時如果超越 cap,系統會重新分配更大的底層數組,原來數組有人用就保留,沒有人用就回收
package main
import "fmt"
func main() {
var s []int //zero value for slice 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}
// 長度是16
s2:=make([]int,16)
s3:=make([]int,10,32)
}
func printSlice(s []int) {
fmt.Printf("len=%d,cap=%dn", len(s), cap(s))
}
// 它每次都是乘以2
聲明 slice
s1:=[]int{2,4,6,8}
// 長度是16
s2:=make([]int,16)
s3:=make([]int,10,32)
fmt.Printf("s1=%v",s1)
fmt.Printf("s2=%v",s2)
fmt.Printf("s3=%v",s3)
copy(s2,s1)
copy(s2, s1)
fmt.Printf("copy(s2,s1)s2=%vn", s2)
printSlice(s2)
刪除 slice delete
fmt.Println("Deleting elements from slice")
s2 = append(s2[:3], s2[4:]...)
fmt.Printf("copy(s2,s1)=>s2=%vn", s2)
printSlice(s2)
從頭或尾刪除
// pop tail
fmt.Println("Popping from front")
front := s2[0]
s2 = s2[1:]
fmt.Println("front=", front)
printSlice(s2)
fmt.Println("Popping from back")
tail := s2[len(s2)-1]
s2 = s2[:len(s2)-1]
fmt.Println(tail)
printSlice(s2)
Map
定義
map[k]vmap[k1]map[k2]v後面可以跟大括號初始化值
m := map[string]string{
"name": "ccmouse",
"course": "golang",
"site": "imooc",
"quality": "notabd",
}
fmt.Println(m)
m2 := make(map[string]int) // m2== empty map
var m3 map[string]int // m3==nil
fmt.Println(m, m2, m3)
// 遍歷
for k, v := range m {
fmt.Println(k, v) //這是無序的
}
// 獲取名字
fmt.Println("Getting values")
courseName := m["course"]
fmt.Println(courseName)
// 如果不存在它會取zero value 本例中就是空串
if courseName, ok := m["cs"]; ok {
fmt.Println(courseName)
} else {
fmt.Println("key does not exist")
}
//刪除元素
fmt.Println("Deleteing values")
name, ok := m["name"]
fmt.Printf("Getting key='name' value=%v is %vn", name, ok)
fmt.Println("Deleting...")
delete(m, "name")
name, ok = m["name"]
fmt.Printf("Getting key='name' value=%v is %vn", name, ok)
- 創建
make(map[string]int) - 獲取
m[key] - key 不存在獲取的 value 類型的初始值(0 值)
- 用
value,ok:=m[key]來判斷是否存在 key - delete()刪除
- range 遍歷,它是無序的,要排序要把 key 放在 slice 中排序再輸出
- map 使用哈希表,必須可以比較相等
- 除了 slice,map,function 的內建類型都可以作為 key
- Struct 類型不包含上述字段,可以作為 key
實例
尋找最長不含有重復字符的子字符串 abcabcbb-->abc
bbbbb->b
pwwkew->wke
對於每一個字母 X
lastOccurred[x]不存在,或者< start無需操作lastOccurred[x]>=start更新 start 將 start 更新到 x+1 的位置- 更新
lastOccurred[x],更新 maxLength
package main
import "fmt"
func nonRep(s string) int {
lastOccurred := make(map[byte]int) //將byte=>rune(支持中文)
start := 0
maxLength := 0
for i, ch := range []byte(s) { //將byte=>rune (支持中文)
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(nonRep("abcabcbb"))
}
上例支持中文
將byte=>rune(支持中文)
主題測試文章,只做測試使用。發佈者:Walker,轉轉請注明出處:https://walker-learn.xyz/archives/6729
