變量的內(nèi)存和變量的地址
指針是一個代表著某個內(nèi)存地址的值。這個內(nèi)存地址往往是在內(nèi)存中存儲的另一個變量的值的起始位置。Go語言對指針的支持介于java語言和C/C+語言之間,它即沒有想Java語言那樣取消了代碼對指針的直接操作的能力,也避免了C/C+語言中由于對指針的濫用而造成的安全和可靠性問題。
package main
import "fmt"
func main() {
var a int = 10
//每個變量有2層含義,變量的內(nèi)存,變量的地址
fmt.Printf("a = %d\n", a) //變量的內(nèi)存 10
fmt.Printf("&a = %p\n", &a) //變量的地址 0xc00000a0c8
}
指針變量的基本使用
//保存某個變量的地址,需要指針類型,*int保存int的地址 **int保存*int地址
var a int = 10
var p *int //定義只是特殊的聲明
p = &a //指針變量指向誰,就把誰的地址賦值給指針變量
fmt.Printf("p = %p, &a = %p\n", p, &a) //p = 0xc00000a0c8, &a = 0xc00000a0c8
*p = 666 //*p操作的不是p的內(nèi)存是所指向的內(nèi)存a
fmt.Printf("*p = %d,a = %d\n", *p, a) //*p = 666,a = 666
不要操作沒有合法的指向的內(nèi)存
var p *int
p = nil
fmt.Println("p = ", p) //<nil>
//*p = 666 //err 因為p沒有合法的執(zhí)行
var a int
p = &a
*p = 666
fmt.Println("a = ", a)
new函數(shù)的使用
表達(dá)式new(T)將創(chuàng)建一個T類型的匿名變量,所做的是T類型的新值分配并清零一塊內(nèi)存空間,然后將這塊內(nèi)存空間的地址作為結(jié)果返回,而這個結(jié)果就是指向這個新的T類型值的指針值,返回的指針類型為*T。
//a :=10 //整型變量a
var p *int
//指向一個合法內(nèi)存
p = new(int) //p是*int,執(zhí)行int類型 new為沒有名字的內(nèi)存
*p = 666
fmt.Println("*p = ", *p)
q :=new(int)
*q = 777
我們只需使用new函數(shù),無需擔(dān)心其內(nèi)存的生命周期或怎樣將其刪除,因為go語言的內(nèi)存管理系統(tǒng)會幫我們打理一切。
普通變量做函數(shù)參數(shù)(值傳遞)
package main
import "fmt"
func swap(a, b int) {
a, b = b, a
fmt.Printf("swap: a = %d, b = %d\n", a, b) // 20 10
}
func main() {
a, b := 10, 20
//通過一個函數(shù)交換a和b的內(nèi)存
swap(a, b) //變量本身傳遞,值傳遞
fmt.Printf("main: a = %d, b = %d\n", a, b) //10 20
}
指針做函數(shù)參數(shù)(地址傳遞)
package main
import "fmt"
func swap(p1, p2 *int) {
*p1, *p2 = *p2, *p1
fmt.Printf("swap: *p1 = %d, *p2 = %d\n", *p1, *p2) // 20 10
}
func main() {
a, b := 10, 20
//通過一個函數(shù)交換a和b的內(nèi)存
swap(&a, &b) //地址傳遞
fmt.Printf("main: a = %d, b = %d\n", a, b) //20 10
}
數(shù)組的基本操作
數(shù)組是指一系列同一類型數(shù)據(jù)的集合。數(shù)組中包含的每個數(shù)據(jù)被稱為數(shù)組元素,一個數(shù)組包含的元素個數(shù)被稱為數(shù)組長度。
package main
import "fmt"
func main() {
//定義一個數(shù)組[10]int和[5]int是不同類型
//[數(shù)組],這個數(shù)字作為數(shù)組元素個數(shù)
var a [10]int
var b [5]int
fmt.Printf("len(a) = %d, len(b) = %d\n", len(a), len(b))
// 注意:定義數(shù)組是,數(shù)組元素個數(shù)必須是常量
//n := 10
//var c [n]int //error non-constant array bound n
//操作數(shù)組元素,從0開始,到len()-1,不對稱元素,這個數(shù)字,叫下標(biāo)
//這是下標(biāo),可以是變量或常量
a[0] = 1
i := 1
a[i] = 2
//賦值,每個元素
for i := 0; i < len(a); i++ {
a[i] = i + 1
}
//打印 第一個返回下標(biāo),第二個返回元素
for i, data := range a {
fmt.Printf("a[%d] = %d\n", i, data)
}
}
數(shù)組初始化
//聲明定義同時賦值,叫初始化
//1 全部初始化
var a [5]int = [5]int{1, 2, 3, 4, 5}
fmt.Println("a = ", a) //a = [1 2 3 4 5]
b := [5]int{1, 2, 3, 4, 5}
fmt.Println("b = ", b) //b = [1 2 3 4 5]
//部分初始化,沒有初始化的元素,自動賦值為0
c := [5]int{1, 2, 3}
fmt.Println("c = ", c) //c = [1 2 3 0 0]
//指定某個元素初始化
d := [5]int{2: 10, 4: 20}
fmt.Println("d = ", d) //d = [0 0 10 0 20]
二維數(shù)組的介紹
//有多個[]就是多少維
//有多少個[]就用多少個循環(huán)
var a [3][4]int
k := 0
for i := 0; i < 3; i++ {
for j := 0; j < 4; j++ {
k++
a[i][j] = k
fmt.Printf("a[%d][%d] = %d, ", i, j, a[i][j])
}
fmt.Printf("\n")
}
fmt.Println("a = ", a) //a = [[1 2 3 4] [5 6 7 8] [9 10 11 12]]
//有3個元素,每個元素又是一維數(shù)組[4]int
b := [3][4]int{
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12},
}
fmt.Println("b = ", b) //b = [[1 2 3 4] [5 6 7 8] [9 10 11 12]]
//部分初始化沒有初始化的值為0
c := [3][4]int{
{1, 2, 3},
{5, 6, 7, 8},
{9, 10},
}
fmt.Println("c = ", c) //c = [[1 2 3 0] [5 6 7 8] [9 10 0 0]]
//部分初始化沒有初始化的值為0
d := [3][4]int{
{1, 2, 3},
{5, 6, 7, 8},
}
fmt.Println("d = ", d) //d = [[1 2 3 0] [5 6 7 8] [0 0 0 0]]
//部分初始化沒有初始化的值為0
e := [3][4]int{0: {1, 2, 3, 4}, 1: {5, 6, 7, 8}}
fmt.Println("e = ", e) //e = [[0 0 0 0] [5 6 7 8] [0 0 0 0]]
數(shù)組比較和賦值
//支持比較,只支持==或!=,比較每一個元素都一樣,2個數(shù)組比較,數(shù)組類型要一樣
a := [5]int{1, 2, 3, 4, 5}
b := [5]int{1, 2, 3, 4, 5}
c := [5]int{1, 2, 3}
fmt.Println("a == b ", a == b) //true
fmt.Println("a == c ", a == c) //false
//同類型的數(shù)組可以賦值
var d [5]int
d = a
fmt.Println("d = ", d) //d = [1 2 3 4 5]
隨機(jī)數(shù)的使用
package main
import (
"fmt"
"math/rand"
"time"
)
func main() {
//設(shè)置種子,只需要一次
//如果種子參數(shù)一樣,每次運行程序產(chǎn)生的隨機(jī)數(shù)都一樣
//rand.Seed(666)
//for i := 0; i < 5; i++ {
// //產(chǎn)生隨機(jī)數(shù)
// fmt.Println("rand = ", rand.Int())//隨機(jī)數(shù)很大的范圍
//}
//rand.Seed(time.Now().UnixNano()) //以當(dāng)前系統(tǒng)時間作為種子參數(shù)
//for i := 0; i < 5; i++ {
// //產(chǎn)生隨機(jī)數(shù)
// fmt.Println("rand = ", rand.Int()) //隨機(jī)數(shù)很大的范圍
//}
rand.Seed(time.Now().UnixNano()) //以當(dāng)前系統(tǒng)時間作為種子參數(shù)
for i := 0; i < 5; i++ {
//產(chǎn)生隨機(jī)數(shù)
fmt.Println("rand = ", rand.Intn(100)) //限制在100內(nèi)的數(shù)
}
}
冒泡排序代碼實現(xiàn)
rand.Seed(time.Now().UnixNano()) //以當(dāng)前系統(tǒng)時間作為種子參數(shù)
var a [10]int
for i := 0; i < len(a); i++ {
a[i] = rand.Intn(100) //100以內(nèi)的隨機(jī)數(shù)
fmt.Printf("%d, ", a[i])
}
fmt.Printf("\n")
//冒泡排序 挨著的2個元素比較,升序(大于則交換)
for i := 0; i < len(a)-1; i++ {
for j := 0; j < len(a)-1-i; j++ {
if a[j] > a[j+1] {
a[j], a[j+1] = a[j+1], a[j]
}
}
}
fmt.Printf("\n排序后:\n")
for i := 0; i < len(a); i++ {
fmt.Printf("%d, ", a[i])
}
fmt.Printf("\n")
數(shù)組做函數(shù)參數(shù)是值拷貝
package main
import "fmt"
// 數(shù)組做函數(shù)參數(shù),他是值傳遞
// 實參數(shù)組的每個元素給形參數(shù)組拷貝一份
// 形參數(shù)組是實參的復(fù)制品,數(shù)組越大,拷貝的效率越低
func modify(a [5]int) {
a[0] = 666
fmt.Println("modify a = ", a)//modify a = [666 2 3 4 5]
}
func main() {
a := [5]int{1, 2, 3, 4, 5}
modify(a) //數(shù)組傳遞過去
fmt.Println("main: a = ", a) //main: a = [1 2 3 4 5]
}
數(shù)組指針做函數(shù)參數(shù)
package main
import "fmt"
// P指向?qū)崊?shù)組a,他是數(shù)組指針
// *p代表指針?biāo)赶虻膬?nèi)存,就是實參a
func modify(p *[5]int) {
(*p)[0] = 666
fmt.Println("modify a = ", *p)
}
func main() {
a := [5]int{1, 2, 3, 4, 5}
//modify a = [666 2 3 4 5]
//main: a = [666 2 3 4 5]
modify(&a) //地址傳遞
fmt.Println("main: a = ", a)
}
切片
切片并不是數(shù)組或數(shù)組指針,它通過內(nèi)部指針和相關(guān)屬性引用數(shù)組片段,以實現(xiàn)邊長方案。
slice并不是真正意義上的動態(tài)數(shù)組,而是一個引用類型。slice總是指向一個底層array,slice的聲明也可以像array一樣,只是不需要長度
a := []int{1, 2, 3, 4, 5}
s := a[0:3:5] //左閉右開
fmt.Println("s = ", s) // s = [1,2,3]
fmt.Println("len(s) = ", len(s)) //長度 //3 3-0
fmt.Println("cap(s) = ", cap(s)) //容量 //5 5-0
s1 := a[1:4:5] //左閉右開
fmt.Println("s = ", s1) // 從下標(biāo)1開始,取4-1=3個 s = [2 3 4]
fmt.Println("len(s) = ", len(s1)) //長度 //3 4-1
fmt.Println("cap(s) = ", cap(s1)) //容量 //4 5-1
切片和數(shù)組區(qū)別
//切片和數(shù)組的區(qū)別
//數(shù)組[]里面的長度是固定的一個常量,數(shù)組不能修改長度,len和cap永遠(yuǎn)都是5
a := [5]int{}
fmt.Printf("len = %d, cap = %d\n", len(a), cap(a)) //len = 5, cap = 5
//切片,[]里面為空,或者為....切片的長度或容易可以不固定
s := []int{}
fmt.Printf("1: len = %d, cap = %d\n", len(s), cap(s)) //1: len = 0, cap = 0
s = append(s, 11) //給切片末尾追加一個成員
fmt.Printf("append: len = %d, cap = %d\n", len(s), cap(s)) //append: len = 1, cap = 1
切片的創(chuàng)建
//自動推導(dǎo)類型 同時初始化
s1 := []int{1, 2, 3, 4}
fmt.Println("s1 = ", s1) //s1 = [1 2 3 4]
//借助make函數(shù) 格式make(切片類型,長度,容量)
s2 := make([]int, 5, 10)
fmt.Printf("len = %d, cap = %d\n", len(s2), cap(s2)) //len = 5, cap = 10
//沒有指定容量,容量和長度一樣
s3 := make([]int, 5)
fmt.Printf("len = %d, cap = %d\n", len(s3), cap(s3)) //len = 5, cap = 5
切片截取
array := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
//[low:high:max] 取下標(biāo)從low開始的元素,len = high-low,cap=max-low
s1 := array[:] //[0:len(array):len(array)] 不指定容量和長度一樣
fmt.Println("s1 = ", s1) //s1 = [0 1 2 3 4 5 6 7 8 9]
fmt.Printf("len = %d, cap = %d\n", len(s1), cap(s1)) //10 10
//操作某個元素和數(shù)組操作方式一樣
data := array[0]
fmt.Println("data = ", data) //0
s2 := array[3:6:7] //a[3] a[4] a[5] len = 3 cap =4
fmt.Println("s2 = ", s2) //3 4 5
fmt.Printf("len = %d, cap = %d\n", len(s2), cap(s2)) //3 4
s3 := array[:6] //從0開始,取6個元素,容量是10 容量為數(shù)組長度
fmt.Println("s3 = ", s3) //[0 1 2 3 4 5]
fmt.Printf("len = %d, cap = %d\n", len(s3), cap(s3)) // 6 10
s4 := array[3:] //從下標(biāo)為3開始,到結(jié)尾
fmt.Println("s4 = ", s4) //[3 4 5 6 7 8 9]
fmt.Printf("len = %d, cap = %d\n", len(s4), cap(s4)) //len = 7, cap = 7
切片和底層數(shù)組關(guān)系
a := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
s1 := a[2:5] //從a[2]開始取三個元素
fmt.Println("s1 =", s1) //[2 3 4]
s1[1] = 666
fmt.Println("s1 =", s1) //s1 = [2 666 4]
fmt.Println("a = ", a) //a = [0 1 2 666 4 5 6 7 8 9]
s2 := s1[1:7]
fmt.Println("s2 = ", s2) //s2 = [666,4 5 6 7 8]
s2[2] = 777
fmt.Println("s2 = ", s2) //s2 = [666 4 777 6 7 8]
fmt.Println("a = ", a) //a = [0 1 2 666 4 777 6 7 8 9]
內(nèi)建函數(shù)------append
append函數(shù)向切片尾部添加數(shù)據(jù),返回新的切片對象,容量不夠,會自動擴(kuò)容
s1 := []int{}
fmt.Printf("len = %d ,cap = %d\n", len(s1), cap(s1)) // 0 0
fmt.Println("s1 = ", s1) //[]
//在原切片的末尾添加元素
s1 = append(s1, 1)
s1 = append(s1, 2)
s1 = append(s1, 3)
fmt.Printf("len = %d ,cap = %d\n", len(s1), cap(s1)) // 3 4 容量以兩倍的速度增加的
fmt.Println("s1 = ", s1) // 1 2 3
s2 := []int{1, 2, 3}
fmt.Println("s2 = ", s2) //1 2 3
s2 = append(s2, 5)
s2 = append(s2, 5)
s2 = append(s2, 5)
fmt.Println("s2 = ", s2) //s2 = [1 2 3 5 5 5]
append擴(kuò)容特點
一旦超過原底層數(shù)組容量,通常以2倍容量重新分配底層數(shù)組,并復(fù)制原來的數(shù)據(jù)
//如果超過原來的容量,通常以2倍容量擴(kuò)容
s := make([]int, 0, 1) //cap 1 len 0
oldCap := cap(s)
for i := 0; i < 8; i++ {
s = append(s, i)
if newCap := cap(s); oldCap < newCap {
fmt.Printf("cap: %d ====>%d\n", oldCap, newCap) //cap: 1 ====>2 cap: 2 ====>4 cap: 4 ====>8
oldCap = newCap
}
}
內(nèi)建函數(shù)copy
srcSlice := []int{1, 2}
dstSlice := []int{6, 6, 6, 6, 6}
copy(dstSlice, srcSlice)
fmt.Println("dst", dstSlice) //dst [1 2 6 6 6]
切片做函數(shù)參數(shù)
切片為引用傳遞
package main
import (
"fmt"
"math/rand"
"time"
)
func InitData(s []int) {
rand.Seed(time.Now().UnixNano()) //設(shè)置種子
for i := 0; i < len(s); i++ {
s[i] = rand.Intn(100) //100以內(nèi)的隨機(jī)數(shù)
}
}
func BubbleSort(s []int) {
n := len(s)
for i := 0; i < n-1; i++ {
for j := 0; j < n-1-i; j++ {
if s[j] > s[j+1] {
s[j], s[j+1] = s[j+1], s[j]
}
}
}
}
func main() {
var n int = 10
//創(chuàng)建一個切片,len為n
s := make([]int, n)
InitData(s)
fmt.Println("排序前 s = ", s)
BubbleSort(s) //冒泡排序
fmt.Println("排序后 s = ", s)
}
猜數(shù)字游戲
package main
import (
"fmt"
"math/rand"
"time"
)
// 創(chuàng)建一個數(shù)字
func CreatNum(p *int) {
rand.Seed(time.Now().UnixNano())
var num int
for {
num = rand.Intn(10000)
if num >= 1000 {
break
}
}
//fmt.Println("num = ", num)
*p = num
}
// 取出每一位
func GetNum(s []int, num int) {
s[0] = num / 1000 //取千位
s[1] = num % 1000 / 100 //取百位
s[2] = num % 100 / 10 //取十位
s[3] = num % 10 //取個位
}
// 猜數(shù)字邏輯
func OnGame(randSlice []int) {
var num int
keySlice := make([]int, 4)
for {
for {
fmt.Printf("請輸入一個4位數(shù)")
fmt.Scan(&num)
if 999 < num && num < 10000 {
break
}
fmt.Println("請輸入的數(shù)不符合要求")
}
//fmt.Println("num = ", num)
GetNum(keySlice, num)
//fmt.Println("keySlice = ", keySlice)
n := 0
for i := 0; i < 4; i++ {
if randSlice[i] < keySlice[i] {
fmt.Printf("第%d位大了一點\n", i+1)
} else if keySlice[i] < randSlice[i] {
fmt.Printf("第%d位小了一點\n", i+1)
} else {
fmt.Printf("第%d位猜對了\n", i+1)
n++
}
}
if n == 4 { //4位都猜對了
fmt.Println("全部猜對")
return
}
}
}
func main() {
var randNum int //產(chǎn)生隨機(jī)的數(shù)
//產(chǎn)生一個4位的隨機(jī)數(shù)
CreatNum(&randNum)
//fmt.Println("randNum: ", randNum)
//切片
randSlice := make([]int, 4)
//保存這個4位數(shù)的每一位
GetNum(randSlice, randNum)
//fmt.Println("randSlice = ", randSlice)
//n1 := 1234 / 1000 //取商
//n2 := (1234 % 1000)/100 //取余 結(jié)果為234
//fmt.Println("n1 = ", n1)
//fmt.Println("n2 = ", n2)
OnGame(randSlice) //游戲
}
map介紹
Go語言中的map(映射,字典)是一種內(nèi)置的數(shù)據(jù)結(jié)構(gòu),他是一個無序的key-value對的集合。
在一個map里所有的鍵都是唯一的,而且必須是支持==和!=操作符的類型,切片。函數(shù)以及包含切片的結(jié)構(gòu)類型這些類型由于具有引用語句,不能作為映射的鍵,使用這些類型會造成便于錯誤
map值可以是任意類型,沒有限制。map里所有鍵的數(shù)據(jù)類型必須是相同的,值也必須如何,但鍵值的數(shù)據(jù)類型可以不相同。
注意:map是無序的,我們無法決定它的返回順序,所以,每次打印結(jié)果的順序有可能不同。
map的基本操作
//map創(chuàng)建
//定義一個變量,類型為map[int]string
var m1 map[int]string
fmt.Println("m1 = ", m1) //m1 = map[]
//對于map只有l(wèi)en,沒有cap
fmt.Println("len = ", len(m1)) //0
//可以通過make創(chuàng)建
m2 := make(map[int]string)
fmt.Println("m2 = ", m2) //m2 = map[]
fmt.Println("len = ", len(m2)) //0
//可以通過make創(chuàng)建,可以指定長度,只是指定了容量,但是里面卻是一個數(shù)據(jù)也沒有
m3 := make(map[int]string, 10)
m3[1] = "mike"
m3[3] = "c++"
m3[2] = "go"
fmt.Println("m3 = ", m3) //m3 = map[1:mike 2:go 3:c++]
fmt.Println("len = ", len(m3)) //3
//鍵值是唯一的
m4 := map[int]string{
1: "make",
2: "go",
3: "c++",
//4:"xxxx",
}
fmt.Println("m4 = ", m4) //m4 = map[1:make 2:go 3:c++]
map賦值
//鍵值是唯一的
m1 := map[int]string{
1: "make",
2: "go",
3: "c++",
//4:"xxxx",
}
//賦值,如果已經(jīng)存在的key值就是修改內(nèi)容
fmt.Println("m1 = ", m1) //m1 = map[1:make 2:go 3:c++]
m1[1] = "python"
fmt.Println("m1 = ", m1) //m1 = map[1:python 2:go 3:c++]
m1[4] = "java" //追加,nap底層自動擴(kuò)容,和append類似
fmt.Println("m1 = ", m1) //m1 = map[1:python 2:go 3:c++ 4:java]
map遍歷
//鍵值是唯一的
m1 := map[int]string{
1: "make",
2: "go",
3: "c++",
//4:"xxxx",
}
//1=========>make
//2=========>go
//3=========>c++
//第一個返回值為key,第二個返回值為value,遍歷結(jié)果是無序的
for key, value := range m1 {
fmt.Printf("%d=========>%s\n", key, value)
}
//如何判斷一個key值是否存在
//第一個返回值為key所對應(yīng)的value,第二個返回值為key是否存在的條件,存在ok為true
value, ok := m1[1]
if ok == true {
fmt.Println("m[1]= ", value) //m[1] make
} else {
fmt.Println("key不存在")
}
map刪除
//鍵值是唯一的
m1 := map[int]string{
1: "make",
2: "go",
3: "c++",
//4:"xxxx",
}
fmt.Println("m1 = ", m1) //m1 = map[1:make 2:go 3:c++]
delete(m1, 1) //刪除key為1的內(nèi)容
fmt.Println("m1 = ", m1) //m1 = map[2:go 3:c++]
map做函數(shù)參數(shù)
引用傳遞
package main
import "fmt"
func test1(m map[int]string) {
delete(m, 1)
}
func main() {
//鍵值是唯一的
m1 := map[int]string{
1: "make",
2: "go",
3: "c++",
//4:"xxxx",
}
fmt.Println("m1 = ", m1) //m1 = map[1:make 2:go 3:c++]
test1(m1)
fmt.Println("m1 = ", m1) //m1 = map[2:go 3:c++]
}
結(jié)構(gòu)體普通變量初始化
結(jié)構(gòu)體類型:
有時我們需要將不同的類型的數(shù)據(jù)組合成一個有機(jī)的整體,如:一個學(xué)生有學(xué)號/姓名/性別等屬性,顯然單獨定義以上變量比較繁瑣,數(shù)據(jù)不便于管理。
結(jié)構(gòu)體是一種聚合的數(shù)據(jù)類型,它是由一系列具有相同類型或不同類型的數(shù)據(jù)構(gòu)成的數(shù)據(jù)集合。每個數(shù)據(jù)稱為結(jié)構(gòu)體的成員。
結(jié)構(gòu)體初始化
package main
import "fmt"
//定義一個結(jié)構(gòu)體類型
type Student struct {
id int
name string
sex byte //字符類型
age int
addr string
}
func main() {
//順序初始化,每個陳冠必須初始化
var s1 Student = Student{1, "mike", 'm', 18, "bj"} //s1 = {1 mike 109 18 bj}
fmt.Println("s1 = ", s1)
//指定成員初始化,沒有初始化的成員自動賦值為零
s2 := Student{name: "mike", addr: "bj"}
fmt.Println("s2 = ", s2) //s2 = {0 mike 0 0 bj}
}
結(jié)構(gòu)體指針變量初始化
package main
import "fmt"
//定義一個結(jié)構(gòu)體類型
type Student struct {
id int
name string
sex byte //字符類型
age int
addr string
}
func main() {
//順序初始化,每個陳冠必須初始化 別忘了&
var p1 *Student = &Student{1, "mike", 'm', 18, "bj"}
fmt.Println("*p1 = ", *p1) //*p1 = {1 mike 109 18 bj}
fmt.Println("p1 = ", p1) //p1 = &{1 mike 109 18 bj}
//指定成員初始化,沒有初始化的成員自動賦值為零
p2 := &Student{name: "mike", addr: "bj"}
fmt.Println("*p2 = ", *p2) //*p2 = {0 mike 0 0 bj}
fmt.Println("p2 = ", p2) //p2 = &{0 mike 0 0 bj}
fmt.Printf("p2 type is %T\n ", p2) //p2 type is *main.Student
}
結(jié)構(gòu)體成員的使用:普通變量
package main
import "fmt"
//定義一個結(jié)構(gòu)體類型
type Student struct {
id int
name string
sex byte //字符類型
age int
addr string
}
func main() {
//定義一個結(jié)構(gòu)體普通變量
var s Student
//操作成員需要使用.運算符
s.id = 1
s.name = "mike"
s.sex = 'm' //字符
s.age = 18
s.addr = "wh"
fmt.Println("s = ", s) //s = {1 mike 109 18 wh}
}
結(jié)構(gòu)體成員的使用:指針變量
package main
import "fmt"
//定義一個結(jié)構(gòu)體類型
type Student struct {
id int
name string
sex byte //字符類型
age int
addr string
}
func main() {
//1 指針有合法指向后,才操作成員
// 先定義一個普通結(jié)構(gòu)體變量
var s Student
//在定義一個指針變量,保存s的地址
var p1 *Student
p1 = &s
//通過指針操作成員p1.id (*p1).id完全等價,只能使用.運算符
p1.id = 1
(*p1).name = "mike"
p1.sex = 'm'
p1.age = 18
p1.addr = "bj"
fmt.Println("p1 = ", p1) //p1 = &{1 mike 109 18 bj}
fmt.Println("*p1 = ", *p1) // *p1 = {1 mike 109 18 bj}
//2 通過new生氣一個結(jié)構(gòu)體
p2 := new(Student)
p2.id = 1
(*p2).name = "mike"
p2.sex = 'm'
p2.age = 18
p2.addr = "bj"
fmt.Println("p2 = ", p2) //p2 = &{1 mike 109 18 bj}
fmt.Println("*p2 = ", *p2) // *p2 = {1 mike 109 18 bj}
}
結(jié)構(gòu)體比較和賦值
如果結(jié)構(gòu)體的全部成員都是可以比較的,那么結(jié)構(gòu)體也是可以可以比較的,那樣的話兩個結(jié)構(gòu)體將可以使用==或!=運算符進(jìn)行比較,但不支持>或<
package main
import "fmt"
//定義一個結(jié)構(gòu)體類型
type Student struct {
id int
name string
sex byte //字符類型
age int
addr string
}
func main() {
s1 := Student{1, "mike", 'm', 18, "bj"}
s2 := Student{1, "mike", 'm', 18, "bj"}
s3 := Student{2, "mike", 'm', 18, "bj"}
fmt.Println("s1 == s3", s1 == s3) //false
fmt.Println("s1 == s2", s1 == s2) //true
//同類型的2個結(jié)構(gòu)體變量可以相互賦值
var tmp Student
tmp = s3
fmt.Println("tmp = ", tmp) //tmp = {2 mike 109 18 bj}
}
結(jié)構(gòu)體做函數(shù)參數(shù):值傳遞
package main
import "fmt"
//定義一個結(jié)構(gòu)體類型
type Student struct {
id int
name string
sex byte //字符類型
age int
addr string
}
func test01(student Student) {
student.id = 2
fmt.Println("test01 student = ", student) //test01 student = {2 mike 109 18 bj}
}
func main() {
s := Student{1, "mike", 'm', 18, "bj"}
test01(s) //值傳遞,形參無法改實參
fmt.Println("main student = ", s) //main student = {1 mike 109 18 bj}
}
結(jié)構(gòu)體做函數(shù)參數(shù):地址傳遞
package main
import "fmt"
//定義一個結(jié)構(gòu)體類型
type Student struct {
id int
name string
sex byte //字符類型
age int
addr string
}
func test01(student *Student) {
student.id = 2
fmt.Println("test01 student = ", *student) //test01 student = {2 mike 109 18 bj}
}
func main() {
s := Student{1, "mike", 'm', 18, "bj"}
test01(&s) //地址傳遞(引用傳遞),形參可以改實參
fmt.Println("main student = ", s) //main student = {2 mike 109 18 bj}
}
go語言可見性規(guī)則驗證
Go語言對關(guān)鍵字的增加非常吝嗇,其中沒有private,protected,public這樣的關(guān)鍵字.
要使某個符號對其他包(package)可見(即可以訪問),需要將符號定義為以大寫字母開頭.文章來源:http://www.zghlxwxcb.cn/news/detail-700694.html
1):如果使用別的包的函數(shù),結(jié)構(gòu)體類型,結(jié)構(gòu)體成員,函數(shù)名,類型名,結(jié)構(gòu)體成員變量名,首字母必須大寫,可見。
2):如果首字母是小寫,只能在同一個包里面使用。文章來源地址http://www.zghlxwxcb.cn/news/detail-700694.html
到了這里,關(guān)于go語言基本操作---三的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!