Go聖經-學習筆記之基礎數據類型

上一篇 Go聖經-學習筆記之程序結構(二)linux

下一篇 Go聖經-臨時插入ORM的小trickgolang

前言

Go語言的數據類型分爲四類:基礎類型複合類型引用類型接口類型。其中數組

  • 基礎類型,包括:int, uintfloat, string, bool
  • 複合類型,包括:結構體數組。它們由一個或者多個元素組成更加複雜的數據結構
  • 引用類型,包括:指針slicemapchanfunc
  • 接口類型

字符串

Go語言源文件都是用UTF-8編碼。 一個字符串是一個不可改變的字節序列,相似C++中的字面字符串,只能讀不能寫。網絡

這裏要注意的是len(string)的長度是指存放在內存中的字節數目(而不是rune字符數目)。因此索引操做s[i]表示內存中第i個字節值。數據結構

i字節並不必定是第i個字符,由於對於非ASCII字符的UTF-8編碼會要多兩個或者多個字節。oop

科普一下ASCII、Unicode和UTF-8之間的關係:學習

  • ASCII是當時美國爲了把英語字符和二進制作映射,一個字節一個字符,一個字節有8位=2^8=256個字符表示,這對英文字符徹底夠用。當時若是引入了漢字等其餘字符,這ASCII表確定是不夠用的
  • Unicode就延伸出來了,它兼容了ASCII表,就是前0-255個數字是徹底對應ASCII表的,從256數字開始就映射的其餘字符,包括中文字符等。那麼Unicode編碼的目的就是要把全世界全部國家的字符所有歸入到其中。可是這裏存在一個問題:可能把全世界的字符所有存儲進來,可能字節大小有4~8個字節那麼多,則ASCII的第一個字符只佔用了一個字節,則剩下的3-7個字節都存儲的0值,嚴重浪費空間,因此須要引入新的編碼方式,儘可能節約內存空間。
  • UTF-8應運而生,Unicode只是一個字符集,UTF-8是Unicode的一種實現方式,目前也是應用最普遍的。UTF-8最大的一個特色:它是一種變長的編碼方式。它可使用1-4個字節表示一個字符。

更多信息,須要本身上網查看。由此,咱們能夠知道,一個字節並不必定表明一個字符。一個rune表示一個字符。ui

字符串字面值

若是一個字符串太長,你想要主動換行,能夠用反引號代替雙引號,它裏面的字符沒有轉義操做,同時能夠跨越多行,例如:編碼

// 格式好看的寫法,使用反引號
    var buffer bytes.Buffer
    buffer.WriteString(`
    SELECT sale_order_id, amount
    FROM sale_order
    WHERE company_id=?
    AND user_id=?
    AND status=?
    `)
    // 格式很差看的寫法,使用雙引號
    buffer.WriteString("SELECT sale_order_id, amount FROM sale_order WHERE company_id=? AND user_id=? AND status=?")
    
    (*o).Raw(buffer.String(), soId, uId, consts.STATUS_OK).QueryRows(&sos)

上面在打orm的日誌時,前者會格式輸出,易讀美觀。後者是一坨,不清晰,看着日誌比較吃力。.net

byte和rune使用

對於中文字符串的輸出:

var s:="hello, "世界"

如今要輸出s字符的個數和遍歷s各個字符,須要藉助utf-8標準庫,有兩種方式實現。

第一種方式:

for i:=0;i<len(s);{
    r, size:=utf8.RuneCountInString(s[i:]) // 獲取一個字符, 且返回一個字符和字符所佔字節數
    fmt.Printf("%d\t%c\n", i, r)
    i+=size
}

第二種方式:

// 這個range是遍歷字符, 隱式解碼
for i, r:= range s{
    fmt.Printf("%d\t%c\t%d", i, r, r)
}

有關字符串處理的標準庫

經常使用的字符串處理的標準庫有四個:bytes, stringsstrconvunicode, 其中前兩個標準庫比較類似,一個針對比特流,一個針對字符串。舉兩個例子簡單使用一下標準庫: 1. 實現相似linux中的basename命令;2.int型的動態數組字符串輸出;

對於第一個,輸入:basename a/b/c.go, 輸出:c

func basename(s string) string{
    slash:=strings.LastIndex(s, "/")
    s = s[slash+1:]
    if dot:= strings.LastIndex(s, "."); dot>=0 {
        s=s[:dot]
    }
    return s
}
func intsToString(elems []int) string{
    var buffer bytes.Buffer
    buffer.WriteString("[")
    for index, elem:= range elems{
        if index >0 {
            buffer.WriteString(", ")
        }
        fmt.Fprintf(&buffer, "%d", elem)
    }
    buffer.WriteString("]")
    return buffer.String()
}

func main(){
    fmt.Println(intsToString([]int{1,2,3}) // "[1, 2, 3]"
}

iota理解和使用

初學者可能對iota的使用不是很瞭解,常量聲明可使用iota常量進行初始化,但不是每一行都須要寫一遍初始化表達式。

明白粗體部分的文字,你就秒懂iota的使用方法。在一個const聲明語句中,在第一個聲明的常量所在行,iota=0,而後在每個有常量聲明的行加一操做, 兩個例子:一個表示一週;一個表示網絡的枚舉

type Weekday int

const (
    Sunday Weekday = iota  // iota =0
    Monday                 // iota =1
    Tuesday                // iota =2
    Wednesday
    Thursday
    Friday                 // ......
    Saturday               // iota = 6
)
type Flags uint

const (
    FlagUp Flags = 1 << iota // is up
    FlagBroadcast            // supports broadcast access capability
    FlagLoopback             // is a loopback interface
    FlagPointToPoint         // belongs to a point-to-point link
    FlagMulticast            // supports multicast access capability
)
// 其實上面表示  xx Flags = 1 << iota, 好比第三行,iota=2;則第三行的常量值等於1<<2 =4。

這樣的解釋和例子,不知道是否明白怎麼樣使用iota常量生成器了。

相關文章
相關標籤/搜索