Go:學習筆記兼吐槽(2) Go:學習筆記兼吐槽(1) Go:學習筆記兼吐槽(2) Go:學習筆記兼吐槽(3)

 

 

Go:學習筆記兼吐槽(1)html

Go:學習筆記兼吐槽(2)數組

Go:學習筆記兼吐槽(3)安全

 

 


 

基本數據類型和string之間的轉換

(1) 基本類型轉string
  • 使用 fmt.Sprintf(「%參數」, 表達式)

a. 通用:bash

參數 含義
%v 值的默認格式表示
%+v 相似%v,但輸出結構體時會添加字段名
%#v 值的Go語法表示
%T 值的類型的Go語法表示
%% 百分號

b. 布爾值:app

參數 含義
%t 單詞true或false

c. 整數:函數

參數 含義
%b 表示爲二進制
%c 該值對應的unicode碼值
%d 表示爲十進制
%o 表示爲八進制
%q 該值對應的單引號括起來的go語法字符字面值,必要時會採用安全的轉義表示
%x 表示爲十六進制,使用a-f
%X 表示爲十六進制,使用A-F
%U 表示爲Unicode格式:U+1234,等價於"U+%04X"

d. 浮點數與複數的兩個組分:post

參數 含義
%b 無小數部分、二進制指數的科學計數法,如-123456p-78
%e 科學計數法,如 -1234.456e+78
%E 科學計數法,如 -1234.456E+78
%f 有小數部分但無指數部分,如123.456
%F 等價於 %f
%g 根據實際狀況採用 %e 或 %f 格式(以得到更簡潔、準確的輸出)
%G 根據實際狀況採用 %E 或 %F 格式(以得到更簡潔、準確的輸出)

e. 字符串和[]byte:學習

參數 含義
%s 直接輸出字符串或者 []byte
%q 該值對應的雙引號括起來的go語法字符串字面值,必要時會採用安全的轉義表示
%x 每一個字節用兩字符十六進制數表示(使用a-f)
%X 每一個字節用兩字符十六進制數表示(使用A-F)

f. 指針:ui

參數 含義
%p 表示爲十六進制,並加上前導的 0x

狂吐槽,這種方式靈活多變,能夠知足全部要求,但實際上大多數狀況下,轉 string 就是想看到一個值本來的樣子,爲何不能每種類型給個默認參數呢?若是有不一樣需求再傳參啊,就像 .net 裏的 ToString() 方法。編碼

  • 使用 strconv 包的函數
func FormatBool(b bool) string
func FormatInt(i int64, base int) string
func FormatUint(i uint64, base int) string
func FormatFloat(f float64, fmt byte, prec, bitSize int) string
func Itoa(i int) string    // ItoaFormatInt(i, 10) 的簡寫

base:指定進制(2到36)
fmt:表示格式:'f'(-ddd.dddd)、'b'(-ddddp±ddd,指數爲二進制)、'e'(-d.dddde±dd,十進制指數)、'E'(-d.ddddE±dd,十進制指數)、'g'(指數很大時用 'e' 格式,不然 'f' 格式)、'G'(指數很大時用 'E' 格式,不然 'f' 格式)。
prec:精度(排除指數部分):對 'f'、'e'、'E',它表示小數點後的數字個數;對 'g'、'G',它控制總的數字個數。若是 prec 爲-1,則表明使用最少數量的、但又必需的數字來表示 f。
bitSize:表示 f 的來源類型(32:float3二、64:float64),會據此進行舍入。

繼續狂吐槽,這種方式太二了,參數都是 64 位的,傳個 int32 還不行,必須先強轉成 int64,這不是浪費效率嗎。並且每種參數類型都對應一個方法,方法名還不一樣,由於,Golang 不支持方法重載

(2) string 轉基本類型
func ParseInt(s string, base int, bitSize int) (i int64, err error)
func ParseUint(s string, base int, bitSize int) (n uint64, err error)
func ParseFloat(s string, bitSize int) (f float64, err error)
func FormatBool(b bool) string
func Atoi(s string) (i int, err error)    // AtoiParseInt(s, 10, 0)的簡寫。

base:指定進制(2到36),若是base爲0,則會從字符串前置判斷,"0x"是16進制,"0"是8進制,不然是10進制。
bitSize:指定結果必須能無溢出賦值的整數類型,0、八、1六、3二、64 分別表明 int、int八、int1六、int3二、int64;簡單的說,若是這個 string 所表示的真實值超出了 baseSize 所指定的類型的範圍,那麼就會發生溢出,雖然這個返回值是 64 位的,然並卵,看下面的例子就明白了。

var str string = "999"
var num int64
num, _ = strconv.ParseInt(str, 108)
fmt.Println(num)  // 結果是 127

都無力吐槽了。
首先這些方法返回兩個值(Golang 容許函數有多個返回值),第一個是轉換結果,64 位的,若是你須要的是一個 32 位的值,那麼還須要強制轉換。
第二個是錯誤信息,若是不想看錯誤信息,能夠用 _ (詳見空標識符)忽略。當發生錯誤時,返回的值是默認值 0。這就是說,你沒辦法 try catch 了。

值類型和引用類型

值類型: int、float、string、bool、數組、結構體struct
引用類型:指針、切片slice、map、管道channel、interface

注意:數組也是值類型,跟其餘語言不一樣。

值類型一般在棧中分配,引用類型一般在堆中分配,當沒有任何一個引用指向該引用類型的地址時,GC 將其回收。

這裏說的是一般,而不是絕對,這是因爲 Golang 中的逃逸機制致使的,這個逃逸機制之後再說。

空標識符

_ 是一個特殊的標識符,稱爲空標識符。它能夠表明其餘任何的標識符,可是它對應的值會被忽略,因此僅能做爲佔位符使用。

訪問級別

Golang 中沒有 public、private 等訪問修飾符,而是規定,常量名、變量名、函數名的首字母若是是大寫的,則能夠被其餘包訪問,若是是小寫的,則其餘包不能訪問。

運算符

(1) 取模

a % b 的運算規則是 a - a / b * b

(2) ++ 和 --

Golang 中,只有 i++,而沒有 ++i
自增和自減只能當作一個獨立的語句使用,j = i++if i++ > 0 等寫法都是錯的。

(3) 三元運算符

Golang 不支持三元運算符,請用 if else

這個我忍。

if

基本語法:

if 條件表達式 {
    語句塊
else {
    語句塊
}
  • 條件表達式不須要() 括起來,在通常狀況下,加了 () 也不會報錯,可是不建議這麼作。若是條件表達式用有定義變量(見下文),那麼加了 () 會報錯。
  • 語句塊必須包含在 {} 中,即使該語句塊中只包含一條語句。(自動加分號致使)
  • else 必須寫在 if 語句塊的 } 後面,不能另起一行。(自動加分號致使)
  • 容許在條件表達式中聲明一個變量,以分號結尾,在這個變量後面再寫條件表達式,這個變量的做用域只在該條件邏輯塊內。
if age := 20; age > 18 {
    fmt.Println("已成年")
else {
    fmt.Println("未成年")
}

我又要開始吐槽了,在條件表達式裏聲明一個變量,看起來不錯。可是,這裏的聲明方式,只能用 := 的方式,不能使用 var 關鍵字來聲明,這就意味着你不能顯示給它指定類型,只能是推導出來的默認類型。而前面也已經說過了,Golang 沒有隱式轉換,不一樣類型之間是沒法比較的。


遇到這種狀況,若是 n 的類型沒法改變,仍是隻能把 age 定義在外面。
最要命的還不是這裏,而是在 for 循環裏,for 循環裏是確定要定義一個循環變量的,不論是在裏面仍是外面,而後這問題就少不了了。

switch

基本語法

switch 表達式 {
    case 表達式1:
        語句塊
    case 表達式2, 表達式3,...:
        語句塊
    default:
        語句塊
}
  • case 後面能夠跟多個表達式,逗號隔開,只要其中一個匹配成功就可進入
  • case 的語句塊中不須要加 break,默認狀況下,語句塊執行完成後就退出 switch
  • switch 後能夠不帶表達式,相似 if else 分支來使用
var age int = 20
switch  {
    case age > 18:
        fmt.Println("已成年")
    default:
        fmt.Println("未成年")
}
  • switch 後也能夠直接聲明一個變量,以分號結束,和 if 相似,但這種寫法不推薦使用。
switch age := 20; {
    case age > 18:
        fmt.Println("已成年")
    default:
        fmt.Println("未成年")
}
  • switch 穿透:在 case 語句塊後增長 fallthrough,則會執行下一個 case。只能穿透一層 case
  • switch 語句還能夠被用於 type-switch 來判斷某個 interface 變量中實際指向的變量類型。

for循環

基本語法:

for i := 1 ; i < 10; i++ {
    語句塊
}

也能夠將循環變量定義或循環變量迭代寫在其餘地方,但分號不能省略,這點跟 .net 等語言是同樣的。

i := 1 
for ;i < 10; i++ {
    語句塊
}

第二種寫法,for 後面能夠僅有循環條件判斷

i := 1 
for i < 10  {
    語句塊
    i++
}

第三種寫法:

for {
    語句塊
}

這種寫法等價於for ; ; {},是一個死循環,一般須要配合 break 使用。
Golang 中沒有 while 和 do while,若是要實現相似的效果,就只能用這個方式。

for range

for range 方式用於遍歷容器類型,如字符串、數組、切片、映射。

var str string = "hello"
for index, value := range str {
    fmt.Printf("%v %c\n", index, value)
}

for range 遍歷字符串的時候是按字節的方式遍歷的,看以下示例:

var str1 string = "hello 北京"
for index, value := range str1 {
    fmt.Printf("%v %c\n", index, value)
}

//運行結果
0 h
1 e
2 l
3 l
4 o
5
6 北
9 京    //注意這裏 index 從 6 直接跳到了 9,由於 UTF-8 編碼一個漢字佔 3 個字節

break 和 continue

break 用於跳出循環,在 .net 等語言中,break 只能用於跳出當前循環,而在 Golang 中,能夠經過標籤指明要跳出哪一層的循環。有點相似 goto 了。

lable1:
for i := 0; i < 10; i++{
    for j := 0; j < 10; j ++{
        if j == 2{
            break lable1
        }
        fmt.Println(j)
    }
}

continuebreak 同樣,也能夠經過標籤指定要繼續的是哪一層循環。

相關文章
相關標籤/搜索