四、基礎語法

四、基礎語法

4.1、注釋

注釋就是對程式碼的解釋和說明,其目的是讓人們能夠更加輕鬆地了解程式碼。注釋是開發人員一個非常重要的習慣,也是專業的一種表現。單行注釋是最常見的注釋形式,你可以在任何地方使用以 // 開頭的單行注釋。多行注釋也叫塊注釋,均已以 /* 開頭,並以 */ 結尾。

注釋只是為了提高可讀性,不會被電腦編譯。

 

4.2、變數

在電腦編程中,我們用變數來保存並管理很多數據,並用變數名來區分、識別和處理這些數據。

變數本質上是一種對記憶體地址的引用,讓你能夠把程式中準備使用的每一段數據都賦給一個簡短、易於記憶的名字進行操作。

4.2.1、聲明變數

和C語言一樣,Go語言也是通過var關鍵字進行聲明,不同的是變數名放在類型前,具體格式如下

var 變數名 變數類型

聲明未賦值,系統默認賦這些類型零值

如果聲明多個變數,可以進行簡寫

package main

import "fmt"

// 全局變數: 定義在函數外的變數

var n7 = 100
var n8 = 9.7

// 設計者認為上面的全局變數的寫法太麻煩了,可以一次聲明:

var (
	n9  = "summer"
	n10 = 21
)

func main() {
	// 定義在{}中的變數叫: 局部變數
	// 第一中變數,變數的使用方式:指定變數的類型,並複製,
	var num int = 20
	fmt.Println(num)

	//第二種: 指定變數的類型,但是不複製,使用默認值
	var num2 int
	fmt.Println(num2)

	// 第三種,如果沒有寫變數的類型,那麼根據後面額值踐行判定變數的類型,(自定類型推斷)
	var num3 = "tom"
	fmt.Println(num3)

	// 第四種: 省略vat, 注意  := 不能寫為=
	sex := "男"
	fmt.Println(sex)

	// 支援一次性聲明多個變數(多變數聲明)
	// 聲明多個變數
	var n1, n2, n3 int
	fmt.Println(n1)
	fmt.Println(n2)
	fmt.Println(n3)

	var n4, name, n5 = 10, "jack", 7.8
	fmt.Println(n4)
	fmt.Println(name)
	fmt.Println(n5)

	n6, height := 6.9, 100.6
	fmt.Println(n6)
	fmt.Println(height)
	fmt.Println(n7)
	fmt.Println(n8)
	fmt.Println(n9)
	fmt.Println(n10)
}

4.2.2、變數賦值

變數賦值的3種方法

(1)變數名=值

// 先聲明再賦值
var x int
x = 10     // 不要 重複聲明 : var x = 10
fmt.Println(x)
x = 20. // 重新賦值

//  直接聲明賦值
// var y string= "hello yuan!"
var y = "hello yuan!"
fmt.Println(y)

// 聲明賦值精簡版
s := "hi,yuan!"  // 1、編譯器會自動根據右值類型推斷出左值的對應類型,等同於var s = "hi,yuan!"。2、該變數之前不能聲明,否則重複聲明
fmt.Println(s)

// 一行聲明賦值多個變數
var name,age = "yuan",22

(2)變數名=變數名

    var a = 100
    var b = a // 變數之間的賦值是值拷貝
    fmt.Println(a, b)
    a = 200
    fmt.Println(b)

3)變數名=值 + 值 (變數名)

     var a, b = 10, 20
    var c = a + b
    fmt.Println(c)
    var d = c + 100
    fmt.Println(d)

4.2.3、匿名變數

匿名變數及沒有命名的變數,在使用多重賦值時,如果想要忽略某個值,可以使用匿名變數(anonymous variable) 匿名變數用一個下劃線_表示

a,b,c :=4,5,6
fmt.Println(a,b,c)
// 如果只想接受第個變數,可以對前兩個變數匿名
_,_,x := 4,5,6
fmt.Println(x)

匿名變數不佔用命名空間,不會分配記憶體

讓程式碼非常清晰,基本上屏蔽掉了可能混淆程式碼閱讀者視線的內容,從而大幅降低溝通的複雜度和程式碼維護的難度。

4.2.4、變數命名規則

變數命名是需要遵循一定的語法規範的,否則編譯器不會通過。

1、變數名稱必須由數字、字母、下劃線組成。

2、標識符開頭不能是數字。

3、標識符不能是保留字和關鍵字。

4、建議使用駝峰式命名,當名字有幾個單片語成的時優先使用大小寫分隔

5、變數名盡量做到見名知意。

6、變數命名區分大小寫

package main

import "fmt"
func main() {
	var 年齡 int = 19
	fmt.Println(年齡)
}


/*
什麼事標識符?
變數,方法等只要是起名字的地方,那個名字就是標識符 var age int = 19 var price float64 = 9.8
標識符定義規則:
1、三個都可以(組成部分): 數字,字母、下劃線_
不建議使用,建議使用字母:46字母

2.四個注意,不可以以數字開頭,嚴格區分大小寫,不能包含空格,不可以使用Go中保留關鍵字
3.見名之意: 增強可讀性
4.下劃線"_" 本身在Go中是一個特殊的標識符,稱為空標識符。可以代表其任何的標識符,但是它對應的值會被忽略(比如: 忽略某個返回值,)所以僅能被作為佔位符使用,
不能單獨作為標識符使用
5.可以用如下形式,但不建議: var int int = 10 (int,float32,float64等不算是保留關鍵字,但是也盡量不要使用)
6.長度無限制,但是不建議太長,asdasdasasdasdadadadadadfasdfcas
7.起包規則
(1)包名:盡量保持package的名字和目錄保持一致,盡量採取有意義的包名,簡短,有意義,不要和標準庫衝突
(1、)為什麼之前在定義源文件的時候,一般我們都用package main 包
main包是一個程式的入口包,所有你main函數它所在的包建議定義為main包,入彀不定義為main包,那麼就不能得到可執行文件。
(2)變數名,函數名、常量名: 採用駝峰法。就是單詞按照大寫區分。
var stuNameDetail string = 'summer'
 (3.) 如果變數名,函數名,常量名字首字母大寫,則可以被其他的包訪問;如果首字母小寫,則只能在本報中使用
 (利用首字母大、小寫完成許可權控制)
注意: import導入語句通常放在文件開頭包聲明語句的下面。導入的包名需要使用雙引號包裹起來。
包名是從$GOPATH/src/後開始計算的,使用/進行路徑分隔。
*/

go語言中有25個關鍵字,不能用於自定義變數名

break        default          func           interface         select
case         defer            go             map               struct
chan         else             goto           package           switch
const        fallthrough      if             range             type
continue     for              import         return            var

還有30多個預定義的名字,用於內建的常量、類型和函數

// 內建常量:
    true false iota nil
// 內建類型:
    int int8 int16 int32 int64
    uint uint8 uint16 uint32 uint64 uintptr
    float32 float64 complex128 complex64
    bool byte rune string error
// 內建函數:
    make len cap new append copy close delete
    complex real imag
    panic recover

4.3、語句分隔符

就像我們寫作文一樣,一定要有像逗號或者句號這樣的語句分隔符,否則無法斷句根本不能理解,程式語言也一樣,需要給解釋器或者編譯器一個語句分割,讓它知道哪裡到哪裡是一個語句,才能再去解析語句。

在 Go 程式中,一行代表一個語句結束。每個語句不需要像 C 家族中的其它語言一樣以分號 ; 結尾,因為這些工作都將由 Go 編譯器自動完成。如果你打算將多個語句寫在同一行,它們則必須使用 ; 人為區分(不建議這樣寫)。

//var name = "yuan";var age = 18 // 不推薦
//fmt.Println(name)
//fmt.Println(age)  // 不報錯但是不推薦

// 推薦寫法
var name = "yuan"  // 換行即分隔符
var age = 18
fmt.Println(name)
fmt.Println(age)

4.4、基本數據類型

基本數據類型包含整型和浮點型,布爾類型以及字元串,這幾種數據類型在幾乎所有程式語言中都支援。

4.4.1、整形

位元組了解:

位元組(Byte):電腦中數據儲存的單位。

位(bit):也叫作「比特」,電腦中數據儲存的最小單位,因為在電腦中是以二進位的形式數據儲存,所以每個位以「0」或「1」表示。

位和位元組的關係是:8個位組成一個位元組。

 位元組與位的關係:1Byte=8bit。

 

  • 整形類型
具體類型 取值範圍
int8 -128到127
uint8 0到255
int16 -32768到32767
uint16 0到65535
int32 -2147483648到2147483647
uint32 0到4294967295
int64 -9223372036854775808到9223372036854775807
uint64 0到18446744073709551615
uint 與平台相關,32位作業系統上就是uint32,64位作業系統上就是uint64
int 與平台相關,32位作業系統上就是int32,64位作業系統上就是int64
var x int
x = 9223372036854775809
fmt.Print(x) // overflows int
package main

import (
	"fmt"
	"unsafe"
)

func main() {
	// 定一個整數類型
	var num1 int8 = 20
	fmt.Println(num1)

	var num2 int8 = 10
	fmt.Println(num2)
	var num3 = 28
	// Pintf函數的作用就是: 格式化的,把num3的類型 填充到%T的位置上
	fmt.Printf("mum3的類型是: %T", num3) //mum3的類型是: int
	//變數佔用的位元組數
	fmt.Println()
	fmt.Println(unsafe.Sizeof(num3))
}
  • 進位轉換
    // 十進位轉化
    var a int = 10
    fmt.Printf("%d \n", a)  // 10    佔位符%d表示十進位
    fmt.Printf("%b \n", a)  // 1010  佔位符%b表示二進位
    fmt.Printf("%o \n", a)  // 12    佔位符%o表示八進位
    fmt.Printf("%x \n", a)  // a     佔位符%x表示十六進位

    // 八進位轉化
    var b int = 020
    fmt.Printf("%o \n", b)  // 20
    fmt.Printf("%d \n", b)  // 16
    fmt.Printf("%x \n", b)  // 10
    fmt.Printf("%b \n", b)  // 10000

    // 十六進位轉化
    var c = 0x12
    fmt.Printf("%d \n", c)  // 18
    fmt.Printf("%o \n", c)  // 22
    fmt.Printf("%x \n", c)  // 12
    fmt.Printf("%b \n", c)  // 10010

4.4.2、浮點型

  • float類型

float類型分為float32float64兩種類型,這兩種浮點型數據格式遵循 IEEE 754 標準。

單精度浮點數佔用4個位元組(32位)存儲空間來存儲一個浮點數。而雙精度浮點數使用 8個位元組(64位)存儲空間來存儲一個浮點數。

單精度浮點數最多有7位十進位有效數字,如果某個數的有效數字位數超過7位,當把它定義為單精度變數時,超出的部分會自動四捨五入。雙精度浮點數可以表示十進位的15或16位有效數字,超出的部分也會自動四捨五入。

浮點類型默認聲明為float64。

package main

import "fmt"

func main() {
	// 定義浮點類型的數據:
	var num1 float32 = 3.14
	fmt.Println(num1)
	// 可以表示在正浮點數,也可以表示服浮點數
	var num2 float32 = -3.14
	fmt.Println(num2)
	//浮點數可以用十進位表示形式,也可以用科學技術法表示形式,E大小寫都可以的
	var num3 float32 = 314e-2
	fmt.Println(num3)
	var num4 float32 = 314e+2
	fmt.Println(num4)
	var num5 float32 = 314e+2
	fmt.Println(num5)
	var num6 float32 = 314e+2
	fmt.Println(num6)

	// 浮點數可能會有精度消失的損失,所以通常情況下。建議你使用:float64
	var num7 float32 = 356.000000916
	fmt.Println(num7)
	var num8 float64 = 356.000000916
	fmt.Println(num8)

	// golang 中默認的浮點類型為: float64
	var num9 = 3.17
	fmt.Printf("num9對應的默認類型為:%T", num9) //num9對應的默認類型為:float64

}
  • 科學計數表示
var f1 = 2e10        // 即使是整數用科學技術表示也是浮點型
fmt.Println(f1,reflect.TypeOf(f1))

var f2 = 2e-2
fmt.Println(f2,reflect.TypeOf(f2))

字元編碼

package main

import "fmt"

func main() {
	// 定義字元類型的數據
	var c1 byte = 'a' // 97
	fmt.Println(c1)
	var c2 byte = '6' // 54
	fmt.Println(c2)
	var c3 byte = '(' //40
	fmt.Println(c3)
	/* 字元類型,本質上就是一個整數,也可以直接參与計算,輸出字元的時候,會將對應的碼值做一個輸出
	   字母,數字,標點等字體,底層是按照ASCII進行存儲。
	*/
	var c4 int = '中'
	fmt.Println(c4)
	/*
		漢子字元,底層對應的是Unicode碼值
		對應的碼值為20013,byte類型溢出,能存儲的範圍,可以用int
		總結:Golang的字符集對應的使用是UTf-8編碼,(Unicode是對應的字符集,UTF-8是Unicode的其中的一種編碼方案)
	*/
	var c5 byte = 'A'
	//想顯示對應的字元,必須採用格式化輸出
	fmt.Printf("c5對應的具體字元為:%c", c5) //c5對應的具體字元為:A
}

4.4.3、布爾類型

布爾是最基本數據類型之一,只有兩個值,True和false,分別代表邏輯判斷中的真和假,主要應用在條件判斷中。

package main

import (
	"fmt"
	"reflect"
)

func main() {
	var b bool
	b = true  //聲明b是一個布爾類型
	b = false // 該類型只有true和false兩個值,分別代表真假兩種狀態
	fmt.Println(b, reflect.TypeOf(b))

	fmt.Println(1 == 1) // 比較運算符的結構是一個布爾值
	//  // fmt.Println(1 == "1") // 報錯,mismatched types不能比較
	fmt.Println(3 > 1)

	var name = "hao"
	var b2 = name == "summer"
	fmt.Println(b2)
}

4.4.4、字元串

字元串是最基本也是最創建的數據類型,是通過雙引號將多個字元按串聯起來的一種數據,用於展示文本

var = "hello wolrd"

單引號只能標識字元

字元串的基本操作

package main

import "fmt"

func main() {
	//1. 定義一個字元串
	var s1 string = "你好全面擁抱golang"
	fmt.Println(s1)
	// 2.字元串是不可以變的: 指的是字元串一旦定義好,其中的字元的值不能改變
	var s2 string = "abc"
	//s2[0] = 't'
	fmt.Println(s2)


	// 字元串的拼接
	var s5 string = "abc" + "def"
	s5 += "hijk"
	fmt.Println(s5)
	// 當一個字元串過長的時候: 注意 + 保留在上一行的最後
	var s6 string = "abc" + "def" + "abc" + "def" + "abc" + "def" + "abc" + "def" + "abc" + "def" + "abc" + "def" +
		"abc" + "def"
	fmt.Println(s6)
}

字元串在記憶體中是一段連續存儲空間

注意:

  1. 索引從零開始計數
  2. go語言不支援負索引
var s = "hello yuan"
fmt.Println(s)

// (1)索引取值 slice[index]  
a:= s[2]
fmt.Println(string(a))

// (2)切片取值slice[start:end], 取出的元素數量為:結束位置 - 開始位置;
b1:=s[2:5]   //
fmt.Println(b1)
b2:=s[0:]    // 當預設結束位置時,表示從開始位置到整個連續區域末尾;
fmt.Println(b2)
b3:=s[:8]    // 當預設開始位置時,表示從連續區域開頭到結束位置;
fmt.Println(b3)

// (3)字元串拼接
var s1 = "hello"
var s2 = "yuan"
var s3 = s1 + s2 // 生成一個新的字元串
fmt.Println(s3)

轉義符

Go 語言的字元串常見轉義符包含回車、換行、單雙引號、製表符等,如下表所示。

轉義符 含義
\r 回車符(返回行首)
\n 換行符(直接跳到下一行的同列位置)
\t 製表符
\' 單引號
\" 雙引號
\\ 反斜杠

舉個例子,我們要列印一個Windows平台下的一個文件路徑:

package main

import "fmt"

func main() {
	var s1 = "hello \nsummer"
	fmt.Println(s1)
	var s2 = "his namme is junue"
	fmt.Println(s2)
	var s3 = "D:\\next\\go.exe"
	fmt.Println(s3)
}

多行字元串

Go語言中要定義一個多行字元串是,就必須使用反引號字元:

package main

import "fmt"

func main() {
    	/*
		3.字元串的表示形式
		(1.)如果字元串中沒有特殊符號,字元串的表示形式用雙引號
		(2.)如果字元串有特殊字元,字元串的表示形式用反引號 ``
	*/

	var s4 string = `package main

import (
	"fmt"
	"reflect"
)

func main() {
	var b bool
	b = true  //聲明b是一個布爾類型
	b = false // 該類型只有true和false兩個值,分別代表真假兩種狀態
	fmt.Println(b, reflect.TypeOf(b))

	fmt.Println(1 == 1) // 比較運算符的結構是一個布爾值
	//  // fmt.Println(1 == "1") // 報錯,mismatched types不能比較
	fmt.Println(3 > 1)

	var name = "hao"
	var b2 = name == "summer"
	fmt.Println(b2)
}`
	fmt.Println(s4)
}

反引號間換行將被作為字元串的換行,但是所有的轉移符均無效,文本將會被原樣輸出。

基本數據類型之間的轉換

package main

import "fmt"

func main() {
	/*
	Go在不同類型的變數之間賦值時,需要顯示轉換,並且只有顯示轉換(強制轉換)
	語法:
	表達式T(v)將值v轉換為類型T
	T: 就是數據類型
	V:就是需要轉換的變數
	 */
	// 進行類型轉換:
	var n1 int = 100
	// var n2 float32 = n1 在這裡自動轉換不好使 ,比如顯示轉換
	fmt.Println(n1)
	//fmt.Println(n2)
	var n2 float32 = float32(n1)
	fmt.Println(n2)
	// 注意: n1的類型其實還是int類型,只是講n1的值100轉為了float32而已,n1還是int的類型
	fmt.Printf("%T", n1) //int
	fmt.Println()

	// 將int64轉為int8的時候,編譯不會出錯的,但是會數據的溢出
	var n3 int64 = 888888
	var n4 int8 = int8(n3)
	fmt.Println(n4) // 56

	var n5 int32 = 12
	var n6 int64 = int64(n5) + 30 //一定要匹配=左右兩邊的數據類型
	fmt.Println(n5)
	fmt.Println(n6)

	var n7 int64 = 12
	var n8 int8 = int8(n7) + 127 // 編譯通過,但是結果可能會溢出
	//var n9 int8 = int8(n7) + 128 //編譯不會通過
	fmt.Println(n8)
	//fmt.Println(n9)
}

基本數據類型轉換為string

package main

import "fmt"

func main() {
	var n1 int = 19
	var n2 float32 = 4.78
	var n3 bool = false
	var n4 byte = 'a'

	var s1 string = fmt.Sprint("%d", n1)
	fmt.Printf("s1對應的類型是:%T, s1 = %q\n", s1, s1)
	var s2 string = fmt.Sprint("%q \n", n2)
	fmt.Printf("s1對應的類型是:%T, s1 = %q\n", s2, s2)
	var s3 string = fmt.Sprint("%q \n", n3)
	fmt.Printf("s1對應的類型是:%T, s1 = %q\n", s3, s3)
	var s4 string = fmt.Sprint("%q \n", n4)
	fmt.Printf("s1對應的類型是:%T, s1 = %q\n", s4, s4)
}
package main

import (
	"fmt"
	"strconv"
)

/*
1.基本數據類型和string的轉換介紹
在程式開發中,我們經常需要講基本數據類型轉換成string類型,或者將string類型轉成基本數據類型。
2.基本類型,string類型
方式一: fmt.Sprinlf("%參數",表達式)  重點練習 推薦方式
方式二: 使用strconv包的函數
*/

func main() {
	var n1 int = 19
	var s1 string = strconv.FormatInt(int64(n1), 10) // 參數: 第一個參數必須轉為int64類型,第二個參數指定字面值的進位形式為十進位
	fmt.Println("對應的類型是: %T, s1 = %q \n", s1, s1)

	var n2 float64 = 4.29
	var s2 string = strconv.FormatFloat(n2, 'f', 9, 64)
	// 第二個參數: 'f' (-ddd.ddd) 第二個參數:9保留小數點後面9位 第四個參數: 表示這個小數是float64類型
	fmt.Printf("對應的類型是: %T ,s2 = %q \n", s2, s2)

	var n3 bool = true
	var s3 string = strconv.FormatBool(n3)
	fmt.Printf("對應的類型是: %T ,s3 = %q \n", s3, s3)
}
package main

import (
	"fmt"
	"strconv"
)

func main() {
	// string 轉換為 bool
	var s1 string = "true"
	var b bool
	/* Parsebool這個函數的返回值有兩個,(value  bool  ,err error)
	   value 就是我們得到的布爾值類型的數據,error出現的錯誤
	   我們只關注得到的布爾類型的數據,err可用用 _直接忽略
	*/
	b, _ = strconv.ParseBool(s1)
	fmt.Printf("b的類型是: %T,b=%v \n", b, b)

	// string 轉換為 int64
	var s2 string = "19"
	var num1 int64
	num1, _ = strconv.ParseInt(s2, 10, 64)
	fmt.Printf("b的類型是: %T,num1=%v \n", num1, num1)

	//string 轉換為float32/float64
	var s3 string = "3.145"
	var f1 float64
	f1, _ = strconv.ParseFloat(s3, 64)
	fmt.Printf("b的類型是: %T,f1=%v \n", f1, f1)

	// 注意 string向基本數據類型轉換的時候,一定要確保string類型能夠轉換成有效的數據類型,否則最後得到的結果就是按照對應的類型的默認值輸出
	var s4 string = "golang"
	var b1 bool

	b1, _ = strconv.ParseBool(s4)
	fmt.Printf("b的類型是: %T,f1=%v \n", b1, b1)

	var s5 string = "golang"
	var num2 int64
	num2, _ = strconv.ParseInt(s5, 10, 64)
	fmt.Printf("b的類型是: %T,f1=%v \n", num2, num2)

}

指針的基本與使用

package main

import "fmt"

func main() {
	var age int = 18
	// & 符號+ 變數 就可以獲取這個變數記憶體的地址
	fmt.Println(&age) //0xc0000b2008

	// 定一個一個指針變數
	// var代表要聲明一個變數
	// ptr 指針變數的名字
	// ptr 對應的類型是: *int 是一個指針類型,(可以理解為,只想int類型的指針)
	// &age就是一個地址, 是ptr變數的具體的值
	var ptr *int = &age
	fmt.Println(ptr)
	fmt.Println("ptr本身這個存儲空間的地址為:", &ptr)

	// 想獲取ptr這個指針或這個地址指向的哪個數據:
	fmt.Println("ptr指向數值為:%v", *ptr) // ptr指向數值為:%v 18
	/*
		總結:最重要的就是兩個符號
		1.& 取記憶體地址
		2. * 根據地址取值
	*/
}

指針的4個細節 

1.可以通過指針改變指向值。

2.指針變數接收的一定是地址值。

3.指針變數的地址不可以不匹配

4.基本數據類型(又叫值類型),都有對應的指針類型,形式為*數據類型,比如int的對應的指針就是*int,float32對應的指針類型就是*float。依次類推

字元串的常用方法

方法 介紹
len(str) 求長度
strings.ToUpper,strings.ToLower 生成一個新的全部大寫的字元串,生成一個新的全部小寫的字元串
strings.ReplaceAll 生成一個新的原字元串被指定替換後的字元串
strings.Contains 判斷是否包含
strings.HasPrefix,strings.HasSuffix 前綴/後綴判斷
strings.Trim 去除字元串兩端匹配的內容
strings.Index(),strings.LastIndex() 子串出現的位置
strings.Split 分割,將字元串按指定的內容分割成數組
strings.Join(a[]string, sep string) join操作,將數組按指定的內容拼接成字元串
package main

import (
    "fmt"
    "reflect"
    "strings"
)

func main() {
    s := "hello world"
    // fmt.Println(len(s))
    // strings.ToUpper 和 strings.ToLower
    s1 := strings.ToUpper("Yuan")
    s2 := strings.ToLower("Rain")
    fmt.Println(s1, s2)

    // strings.Trim
     user := "  yuan "
    fmt.Println(len(user))
    fmt.Println(strings.TrimLeft(user, " "))
    fmt.Println(strings.TrimSpace(user))
    fmt.Println(strings.Trim(user, " "))

    s := "alvin,yuan,eric"
    // strings.Index,strings.LastIndex
    var index = strings.Index(s, "yuan!")
    fmt.Println(index) // 未找到返回-1
    var index2 = strings.LastIndex(s, "l")
    fmt.Println(index2)

    // strings.HasPrefix,strings.HasSuffix,strings.Contains(實現的依賴的就是strings.Index)
    fmt.Println(strings.HasPrefix(s, "alv"))
    fmt.Println(strings.HasSuffix(s, "eric"))
    fmt.Println(strings.Contains(s, "eric"))

    // strings.Split: 將字元串分割成數組
    var ret2 = strings.Split(s, ",")
    fmt.Println(ret2, reflect.TypeOf(ret2))

    // strings.Join:將數組拼接成字元串
    var ret3 = strings.Join(ret2, "-")
    fmt.Println(ret3, reflect.TypeOf(ret3))

}

4.4.6、類型轉換

Go語言中只有強類型轉換,沒有隱式類型轉換,改語法只能在兩個類型之間支援想換轉換的時候使用。


    // (1)整型之間的轉換
    var a int8
    a = 99
    fmt.Println(int64(a), reflect.TypeOf(int64(a)))
    fmt.Println(float64(a), reflect.TypeOf(float64(a)))

    // (2)string與int類型的轉換
    x := strconv.Itoa(98)
    fmt.Println(x, reflect.TypeOf(x))
    y, _ := strconv.Atoi("97")
    fmt.Println(y, reflect.TypeOf(y))

    // (3) Parse系列函數

    //  ParseInt
    //  輸入:1.數字的字元串形式 2.base,數字字元串的進位,比如:2進位、10進位。
    //       3.bitSize的含義是⼤⼩限制,如果字元串轉化的整形數據類型超過bitSize的最大值,那麼輸出的int64為bitSize的最大值,err就會顯⽰數據超出範圍。
    i1, _ := strconv.ParseInt("1000", 10, 8)
    println(i1)
    i2, _ := strconv.ParseInt("1000", 10, 64)
    println(i2)

    f2, _ := strconv.ParseFloat("3.1415926", 64)
    fmt.Println(f2, reflect.TypeOf(f2))
    f1, _ := strconv.ParseFloat("3.1415926", 32)
    fmt.Println(f1, reflect.TypeOf(f1))

    // 返回字元串表示的bool值。它接受1、0、t、f、T、F、true、false、True、False、TRUE、FALSE;否則返回錯誤。
    b1, _ := strconv.ParseBool("true")
    fmt.Println(b1, reflect.TypeOf(b1))
    b2, _ := strconv.ParseBool("T")
    fmt.Println(b2, reflect.TypeOf(b2))
    b3, _ := strconv.ParseBool("1")
    fmt.Println(b3, reflect.TypeOf(b3))
    b4, _ := strconv.ParseBool("100")
    fmt.Println(b4, reflect.TypeOf(b4))

4.5、運算符

一個程式的最小單位是一條語句,一條語句最少包含一條指令,而指令就是對數據做運算,我們已經學完基本數據類型了,知道如何構建和使用一些最簡單的數據,那麼我們能對這些數據做什麼運算呢,比如fmt.Println(1+1)這條語句包含兩個指令,首先是計算1+1的指令,1就是數據,+就是算術運算符中的相加,這樣電腦就可以幫我們執行這個指令計算出結果,然後執行第二個指令,即將計算結果2列印在終端,最終完成這條語句。

4.5.1、算數運算符

運算符 描述
+ 相加
相減
* 相乘
/ 相除
% 求余

如何判斷一個整型數字是奇數還是偶數?

package main

import "fmt"

func main() {
	// 加號
	// 1.正數。 2.相加操作 3.字元串拼接
	var n1 int = +10
	fmt.Println(n1)
	var n2 int = 4 + 7
	fmt.Println(n2)
	var n3 string = "你好" + "summer"
	fmt.Println(n3)

	fmt.Println(10 / 3)   // 兩個int類型數據運算,結果一定為整數類型
	fmt.Println(10.0 / 3) // 浮點類型參與運算,結果為浮點類型。

	// % 取模 等價公式 a%b=a-a/b*b
	fmt.Println(10 % 3)
	fmt.Println(-10 % 3)
	fmt.Println(10 % -3)
	fmt.Println(-10 % -3)

	// ++ 自增操作:
	var a int = 10
	a++
	fmt.Println(a)
	// ++ 自增加1操作, --自減操作
	// go語言里, ++ ,--操作非常簡單,只能單獨使用,不能參與到運算中去
	// gp語言里,++ ,--只能在變數的後面,不能寫在變數的前面, --a   ++a 錯誤寫法
}

4.5.2、關係運算符

運算符 描述
== 檢查兩個值是否相等,如果相等返回 True 否則返回 False。
!= 檢查兩個值是否不相等,如果不相等返回 True 否則返回 False。
> 檢查左邊值是否大於右邊值,如果是返回 True 否則返回 False。
< 檢查左邊值是否小於右邊值,如果是返回 True 否則返回 False。
>= 檢查左邊值是否大於等於右邊值,如果是返回 True 否則返回 False。
<= 檢查左邊值是否小於等於右邊值,如果是返回 True 否則返回 False。

4.5.3、邏輯運算符

運算符 描述
&& 邏輯 AND 運算符。 如果兩邊的操作數都是 True,則條件 True,否則為 False。
|| 邏輯 OR 運算符。 如果兩邊的操作數有一個 True,則條件 True,否則為 False。
! 邏輯 NOT 運算符。 如果條件為 True,則邏輯 NOT 條件 False,否則為 True。
package main

import "fmt"

func main() {
	// 與邏輯:   && : 兩個數值/表達式只要有一側是false,結果一定為false
	// 也叫短路與: 只要第一個數值/表達式的結果是false,那麼後面的表達式等就不用運算了,直接結果是false
	fmt.Println(true && true)
	fmt.Println(true && false)
	fmt.Println(false && true)
	fmt.Println(false && false)

	//或邏輯 ||: 兩個數值、表達式只要有一側是true, 結果一定是為true
	// 也叫短路或: 只要第一個數值/表達式的結果是true,那麼後面的表達式等就不用運算了,直接結果是true
	fmt.Println(true || true)
	fmt.Println(true || false)
	fmt.Println(false || true)
	fmt.Println(false || false)

	//非邏輯 : 取相反的結果
	fmt.Println(!true)
	fmt.Println(!false)

	/*
		其他運算符:
		& :返回變數的存儲地址
		* : 取指針變數對應的數值
	*/
	var age int = 18
	fmt.Println("age對應的存儲空間的地址為:", &age) //age對應的存儲空間的地址為: 0xc000018088
	var ptr *int = &age
	fmt.Println(ptr)
	fmt.Println("ptr這個指針指向的具體 數值為", *ptr) // ptr這個指針指向的具體 數值為 18
}

4.5.4、賦值運算符

運算符 描述
= 簡單的賦值運算符,將一個表達式的值賦給一個左值
+= 相加後再賦值
-= 相減後再賦值
*= 相乘後再賦值
/= 相除後再賦值
%= 求余後再賦值
«= 左移後賦值
»= 右移後賦值
&= 按位與後賦值
^= 按位異或後賦值
|= 按位或後賦值
++ 自增
自減

4.5.5、運算符優先順序

 一句話: 為了提高優先順序,可以加()

 

4.6、輸入輸出函數

4.6.1、輸出函數

fmt.Print有幾個變種:

Print: 輸出到控制台,不接受任何格式化操作 Println: 輸出到控制台並換行 Printf : 只可以列印出格式化的字元串,只可以直接輸出字元串類型的變數(不可以輸出別的類型) Sprintf:格式化並返回一個字元串而不帶任何輸出

(1)Print 和Println

Print和Println()函數可以列印出字元串或變數的值。

    name := "yuan"
    age := 24

    fmt.Print(name, age)

    fmt.Println("hello world")
    fmt.Println(name)
    fmt.Println(age)
    fmt.Println(name, age)
    fmt.Println("姓名:", name, "年齡:", age)

(2)格式化輸出(Printf)

Printf根據格式說明符號格式化並寫入標準輸出。Printf只列印字元串

比如上面列印一個人的基本細膩格式:

  name := "yuan"
  age := 24
  isMarried := false
  salary := 3000.549
  fmt.Printf("姓名:%s 年齡:%d 婚否:%t 薪資:%.2f\n", name, age, isMarried, salary)
  fmt.Printf("姓名:%v 年齡:%v 婚否:%v 薪資:%v\n", name, age, isMarried, salary)
  fmt.Printf("姓名:%#v 年齡:%#v 婚否:%#v 薪資:%#v\n", name, age, isMarried, salary)
 
%v:以默認的方式列印變數的值
%#v:相應值的Go語法表示
%T:列印對應值的類型
%+d :帶符號的整型,%d 不帶符號的整型
%o :不帶零的八進位,%#o 帶零的八進位
%x :小寫的十六進位,%X 大寫的十六進位,%#x 帶0x的十六進位
%b :列印整型的二進位
%t :列印true 或 false
%s:輸出字元串表示,%-5s 最小寬度為5(左對齊)
%f 小數點而無指數,默認精度為6
%e 科學計數法,如-1234.456e+78
%p 帶0x的指針,%#p 不帶0x的指針

 

// 整形和浮點型
fmt.Printf("%b\n", 12)  // 二進位表示:1100
fmt.Printf("%d\n", 12)  // 十進位表示:12
fmt.Printf("%o\n", 12)  // 八進位表示:14
fmt.Printf("%x\n", 12)  // 十六進位表示:c
fmt.Printf("%X\n", 12)  // 十六進位表示:c
fmt.Printf("%f\n", 3.1415)  // 有小數點而無指數:3.141500
fmt.Printf("%.3f\n", 3.1415)  // 3.142
fmt.Printf("%e\n", 1000.25)  // 科學計數法:  1.000250e+03,默認精度為6

// 設置寬度
fmt.Printf("學號:%s 姓名:%-20s 平均成績:%-4d\n", "1001", "alvin", 100)
fmt.Printf("學號:%s 姓名:%-20s 平均成績:%-4d\n", "1002", "zuibangdeyuanlaoshi", 98)
fmt.Printf("學號:%s 姓名:%-20s 平均成績:%-4d\n", "1003", "x", 78)

(3)Sprintf

Printf和Sprintf都是替換字元串,Printf是直接輸出到終端,Sprintf是不直接輸出到終端,而是返回該字元串

     name := "yuan"
    age := 24
    isMarried := false
    salary := 3000.549
    info := fmt.Sprintf("姓名:%s 年齡:%d 婚否:%t 薪資:%.2f\n", name, age, isMarried, salary)
    fmt.Println(info)

4.6.2、輸入函數

go語言fmt包下有三個函數,可以在程式運行過程中從標準輸入獲取用戶的輸入:

(1)fmt.Scan

語法

func Scan(a ...interface{}) (n int, err error)
  • Scan 從標準輸入掃描文本,讀取由空白符分隔的值保存到傳遞給本函數的參數中,換行符視為空白符。
  • 本函數返回成功掃描的數據個數和遇到的任何錯誤。如果讀取的數據個數比提供的參數少,會返回一個錯誤報告原因。

fmt.Scan從標準輸入中掃描用戶輸入的數據,將以空白符分隔的數據分別存入指定的參數中。

(2)fmt.Scanf

語法

func Scanf(format string, a ...interface{})(n int, err error)
  • Scanf從標準輸入掃描文本,根據format參數指定的格式去讀取由空白符分隔的值保存到傳遞給本函數的參數中。
  • 本函數返回成功掃描的數據個數和遇到的任何錯誤。

 

package main

import "fmt"

func main() {
	// 方式一: Sacnf
	var age int
	var name string
	var score float32
	var isVIP bool

	fmt.Println("請輸入學生的年齡,姓名,成績,是否是VIP,使用空格進行分隔")
	fmt.Scanf("%d %s %f %t", &age, &name, &score, &isVIP)
	fmt.Printf("學生的年齡圍毆:%v,姓名為:%v,成績為:%v,是否為VIP:%v,", age, name, score, isVIP)
}

(3)fmt.Scanln

語法

func Scanln(a ...interface{}) (n int, err error)

 

  • Scanln類似於Scan,它遇到換行立即停止掃描。
  • 本函數返回成功掃描的數據個數和遇到的任何錯誤。

Scanln和Scan的區別就是Scanln遇到換行立即結束輸入,而Scan則會將換行符作為一個空白符繼續下一個輸入

package main

import "fmt"

func main() {
	// 實現功能,鍵盤錄入學生的年齡,姓名,,成績,是否是VIP
	// 方式二 Scanln
	var age int
	fmt.Println("請錄入學生的年齡:")
	// 傳入age的地址的目的:在Scanln函數中,對地址中的值進行改變的時候,實際外面的age被影響了
	fmt.Scanln(&age) //錄入數據的時候,類型一定要匹配,因為底層會自動判定類型的

	var name string
	fmt.Println("請錄入學生的姓名:")
	fmt.Scanln(&name)

	var score float32
	fmt.Println("請錄入學生的成績:")
	fmt.Scanln(&score)

	var isvip bool
	fmt.Println("請錄入學生是否為VIP:")
	fmt.Scanln(&isvip)

	// 將上述數據在控制台列印輸出:
	fmt.Printf("學生的年齡圍毆:%v,姓名為:%v,成績為:%v,是否為VIP:%v,", age, name, score, isvip)
}

4.7、常量與itoa

 常量是一個簡單的標識符,在程式運行時, 不會被修改的量,在Python、Java變成規範中,常量一般都是全大小字母,但是Golang中,大小寫是具有特殊含義的,所以不一定所有常量都得大寫

4.7.1 常量

常量是⼀個簡單值的標識符,在程式運⾏時,不會被修改的量。 在Python、Java編程規範中,常量⼀般都是全⼤寫字母,但是在Golang中,⼤⼩寫是具有⼀定特殊含義的,所以不⼀定所有常量都得全⼤寫。

聲明賦值方式與變數接近,通過const實現

const 常量名[數據類型] = value

數據類型可以忽略不寫,Golang編譯器會⾃動推斷出數據類型。 在使⽤時,要注意以下⼏點:

  1. 數據類型只可以是布爾型、數字型(整數型、浮點型和複數)和字元串型
  2. 滿⾜多重賦值
  3. 常量只定義不使⽤,編譯不會報錯
  4. 常量可以作為枚舉,常量組
  5. 常量組中如不指定類型和初始化值,則與上⼀⾏⾮空常量右值相同
  6. 顯⽰指定類型的時候,必須確保常量左右值類型⼀致,需要時可做顯⽰類型轉換。

 

    // (1)聲明常量
    const pai = 3.1415926
    const e float64 = 2.7182818
    fmt.Println(pai * pai)

    // (2)常量也可以和變數一樣一組一起聲明
    // const monday, tuesday, wednesday = 1, 2, 3
    // 更推薦下面這種方式
    const (
        monday    = 1
        tuesday   = 2
        wednesday = 3
        thursday  = 4
        friday    = 5
        saturday  = 6
        sunday    = 7
    )

    const (
        female = 0
        male   = 1
    )

    // ⼀組常量中,如果某個常量沒有初始值,默認和上⼀⾏⼀致

    const (
        a int = 1
        b
        c = 2
        d
    )
    fmt.Println(a, b, c, d)

4.7.2 iota計數器

iota是go語言的常量計數器,只能在常量的表達式中使用。 使用iota時只需要記住以下兩點

1.iotaconst關鍵字出現時將被重置為0。

2.const中每新增一行常量聲明將使iota計數一次(iota可理解為const語句塊中的行索引)。

 

const (
        food = iota
        cloth
        bed
        electric
    )

    fmt.Println(food, cloth, bed, electric)

    const (
        a = 1
        b = iota
        c = 6
        d
        e = iota
        f
    )

    fmt.Println(a, b, c, d, e, f)
const (
        b  = 1 << (iota * 10)
        kb 
        mb 
        gb 
        tb
        pb 
    )
fmt.Println(b, kb, mb, gb, tb, pb)

 

Tags: