1. 程式人生 > >(二)go的基礎資料結構型別

(二)go的基礎資料結構型別

1.go的常量

package main

import "fmt"

/*
常量是指程式執行時不可改變的值,常量必須初始化值。定義常量既可以指定型別,編譯器也可以在常量初始化時做型別判斷。
並且在函式程式碼塊中定義常量,不被使用也不會出現編譯錯誤。
在常量組中,如果不指定型別和常量值,那麼常量的型別和值回和上一個常量的型別和值相同
 */

const a = 1 //用const關鍵字表明a是一個常量
const b = "satori"

//也可以一次性初始化多個常量
const c,d,e = "4", 5, "6"

//也可以以常量組的形式初始化
const (
	f = "python"
	g //此時g什麼都不寫,那麼和它的上一個常量f的值與型別是一樣的,等價於g = "python"
)

//iota,預設為零,並且自增1
const (
	h = iota //iota初始化為零,等價於h = 0
	i //不寫的話,等價於i = iota,但是iota會增加,因此等價於i = 1
)

const (
	x = 2 << iota //iota初始化為零,等價於x = 2 << 0
	y //iota預設加一,等價於 y = 2 << 1
	z = 666 //z我指定了值,那麼z就等於我指定的666。但此時的iota依舊在增加,此時iota = 2
	w //由於z的出現,w不指定的話不會等於2 << 3,而是和z一樣也等於666,和上一個常量一致。但是別忘記此時iota = 3
	k = 3 << iota //此時的k = 3 << iota就等價於k = 3 << 4
	s //s不寫的話等價於s = 3 << iota,但此時iota=5,因此相當於s = 3 << 5

)
func main(){
	// 這裡的%v表示萬能列印,可以列印所有型別的值
	fmt.Printf("a = %v\n", a)
	fmt.Printf("b = %v\n", b)
	fmt.Printf("c = %v\n", c)
	fmt.Printf("d = %v\n", d)
	fmt.Printf("e = %v\n", e)
	fmt.Printf("f = %v\n", f)
	fmt.Printf("g = %v\n", g)
	fmt.Printf("h = %v\n", h)
	fmt.Printf("i = %v\n", i)
	fmt.Printf("x = %v\n", x)
	fmt.Printf("y = %v\n", y)
	fmt.Printf("z = %v\n", z)
	fmt.Printf("w = %v\n", w)
	fmt.Printf("k = %v\n", k)
	fmt.Printf("s = %v\n", s)
}
//輸出結果 /* a = 1 b = satori c = 4 d = 5 e = 6 f = python g = python h = 0 i = 1 x = 2 y = 4 z = 666 w = 666 k = 48 s = 96 */

  

2.go的變數

package main

import "fmt"

/*
變數就是可以改變的量,並且在go語言中,變數一旦宣告必須使用,否則報錯
 */
func main() {
	var a= 1 // 初始化一個變數a = 1

	//也可以先宣告一個變數然後再初始化
	var b string //聲明瞭一個變數b,這個變數的值的型別為string
	// 給b賦值
	b = "satori"

	//我們之前說的常量一旦宣告必須賦值,但是變數不需要
	//在go中,如果變數不初始化,go語言會預設初始化一個0值
	//舉個例子
	var c int
	var d string
	var e [3]int
	var f bool
	fmt.Printf("a = %v\n", a)
	fmt.Printf("b = %v\n", b)
	fmt.Printf("c = %v\n", c)
	fmt.Printf("d = %q\n", d)  //這裡使用%q,可以打印出雙引號
	fmt.Printf("e = %v\n", e)
	fmt.Printf("f = %v\n", f)
}
//輸出結果
/*
a = 1
b = satori
c = 0
d = ""
e = [0 0 0]
f = false
 */

  

3.go的字串

package main

import "fmt"

func main(){
	//宣告並初始化一個字串
	var s = "satori"
	fmt.Println(s) //satori

	//獲取字串的第一個字元,但是這樣列印的是一個bytes,需要轉成字元輸出
	fmt.Println(string(s[0])) //s

	//獲取最後一個字元,在go中沒有-1這個說法,可以使用string[長度-1]
	//那麼字串的長度如何獲取呢?這個和python是一樣的,可以使用len獲取
	fmt.Println(string(s[len(s)-1])) //i

	//也可以使用range遍歷
	/*
	關於range,如果指定一個值那麼獲取的就是索引
	如果指定兩個值,那麼分別獲取索引和值
	 */
	var name = "satori"
	for k:=range name{
		fmt.Println(k)
		/*
		0
		1
		2
		3
		4
		5
		 */
	}
	for k,v:=range name{
		fmt.Println(k,string(v))
		/*
		0 s
		1 a
		2 t
		3 o
		4 r
		5 i
		 */
	}
	//但是如果我想只想要值,又不想要索引呢?因為在go中如果聲明瞭,必須使用,這是怎麼辦呢?可以使用_
	for _, v:=range name{ // _表明這個值我要它沒用
		fmt.Println(string(v))
		/*
		s
		a
		t
		o
		r
		i
		 */
	}

	//這種遍歷方式還有一個問題,這個問題在python中是不存在的。那就是中文
	var username = "古明地覺"
	//由於go的索引,比如說username[0],表示獲取username字串的第1個位元組
	//英文一個字元佔一個位元組,所以沒問題,但是中文一個佔三個位元組,所以會出問題
	fmt.Println(string(username[0])) // å, 列印的結果是這麼個玩意

	//但是使用range遍歷獲取值是沒有問題的,但是如果想通過索引正常獲取的話,怎麼辦呢?
	//可以使用[]rune(),[]rune(username)便是按照字元來獲取
	fmt.Println(string([]rune(username)[0])) //古

	//在比方說,我們獲取長度,按照位元組肯定是12個,因為go採用utf-8編碼,按照字元那麼佔4個。在python中使用len佔4個
	fmt.Printf("len(username)=%d, len([]rune(username)=%d\n", len(username), len([]rune(username))) //len(username)=12, len([]rune(username)=4
}

那麼go的字串都有哪些操作呢?

package main
 
import (
    "fmt"
    "regexp"
    "strconv"
    "strings"
)
 
func main(){
    //1.檢視字串中是否包含某個子串,類似於Python中的__contains__,或者 in
    fmt.Println(strings.Contains("古明地覺", "古明"))//true
    fmt.Println(strings.Contains("古明地覺", "古明地覺"))//true
    fmt.Println(strings.Contains("古明地覺", "古明地盆"))//false
 
    //2.將多個字串按照一定規則組合在一塊,類似於Python中的join
    s := []string{"古明地盆","東方地靈殿"}
    fmt.Println(strings.Join(s, "來自"))//古明地盆來自東方地靈殿
 
    //3.查詢字串中某個子串的位索引,查不到為-1,類似於Python中的find
    fmt.Println(strings.Index("satori","ri"))//4
    fmt.Println(strings.Index("satori","shi"))//-1
 
    //4.將一個字串重複n次,類似Python中的*
    fmt.Println(strings.Repeat("satori", 3)) //satorisatorisatori
 
    //5.將一個字串按照指定字元進行切割,類似於Python中的split
    s1:="satori|koishi|古明地盆|古明地戀"
    fmt.Println(strings.Split(s1, "|"))//[satori koishi 古明地盆 古明地戀]
 
    //6.去掉字串兩頭,類似於Python中的strip
    fmt.Println(strings.Trim("aababbb古明地盆古明地戀bababaa", "ab"))//古明地盆古明地戀
 
    //7.去掉所有的空格,將元素放在一個切片中
    fmt.Println(strings.Fields("    are      古明地盆    ok"))//[are 古明地盆 ok]
 
    //8.計算指定字元出現的次數
    fmt.Println(strings.Count("古明地盆古明地戀", "古"))//2
 
    //9.判斷字串是否以指定字元開頭
    fmt.Println(strings.HasPrefix("satori", "sa"))//true
 
    //10.判斷字串是否以指定字元結尾
    fmt.Println(strings.HasSuffix("satori","ri"))//true
 
    //----------------------------
 
    //1.轉化為字串後追加到位元組陣列
    slice := make([]byte, 0, 1024)
    slice = strconv.AppendBool(slice, true)
    //第三個引數表示以多少進位制追加
    slice = strconv.AppendInt(slice, 1024, 10)
    slice = strconv.AppendQuote(slice, "satori")
    slice = strconv.AppendQuote(slice, "古明地盆")
    //轉化為字串列印
    fmt.Println(string(slice)) //true1024"satori""古明地盆"
 
    //2.字串轉整型
    //具有兩個返回值,另一個是錯誤資訊
    fmt.Println(strconv.Atoi("6666")) //6666 <nil>
 
    //3.整型轉字串
    fmt.Println(strconv.Itoa(2333)) //2333
    fmt.Printf("%q\n", strconv.Itoa(2333))//"2333"
 
 
    //正則表示式,熟悉Python的話,這個自不必說,只介紹不同的地方
    //Python表示原生字串需要在""前面加上r,go中使用``表示即可
    //步驟分為兩步
    //1.使用MustCompile解析並返回一個正則表示式
    reg := regexp.MustCompile(`\d{4}`)
    //2.呼叫需要的函式查詢
    result1 := reg.FindAllString("123-1234-12345",-1)
    result2 := reg.FindAllStringSubmatch("123-1234-12345",-1)
    fmt.Println(result1)//[1234 1234]
    fmt.Println(result2)//[[1234] [1234]]
}