一、指針
//指針 獲取對象、變量的內存地址
//取地址符是 &,放到一個變量前使用就會返回相應變量的內存地址。
//指針類型前面加上 * 號(前綴)來獲取指針所指向的內容
func pointDef() {
//定義指針變量
var ip *int /* 指向整型*/
//獲取變量地址
a := 1
fmt.Println("變量的內存地址:", &a)
//通過指針變量訪問目標地址
ip = &a
fmt.Println("ip變量的目標指針存儲地址:", ip)
fmt.Println("ip指針所指向的內容:", *ip)
//空指針
var ptr *int
if (ptr == nil) {
fmt.Printf("ptr 爲空指針,值爲 : %x\n", ptr)
}
//向函數傳遞指針
b := 2
var x *int
var y *int
x = &a
y = &b
//傳入指針 值分別爲1 2
swap(x, y)
}
//指針傳入函數
func swap(x *int, y *int) {
var temp int
//指針傳值
temp = *x //x指針指向的值賦值給tmp
fmt.Println("temp:", temp)
*x = *y //y指針指向的值,賦值給x指針
fmt.Println("*x:", *x)
fmt.Println("x賦值給y前,y地址:", y)
*y = temp //temp 賦值給y值
fmt.Println("*y:", *y)
//打印指針指向地址
fmt.Println("x地址:", x)
fmt.Println("y地址:", y)
}
二、結構體
//聲明結構體; 等同java 對象
type Book struct {
title string
author string
}
func stuctDef(){
//實例化book
var goBook Book
goBook.title = "Go"
goBook.author = "Max"
//book屬性引用
fmt.Println(goBook.title)
}
三、range遍歷
//range 數組 ,用於遍歷圈定遍歷範圍
func rangeDef() {
//準備一個slice數組
nums := []int{2, 3, 4}
sum := 0
//利用range遍歷數組進行求和;_ 表示不用關注循環的i次數
for _, num := range nums {
if num == 3 {
fmt.Println("range中做判斷", 3)
}
sum += num
}
fmt.Println("sum:", sum)
//利用range 遍歷map的kv
//聲明一個map
kvs := map[string]string{"a": "apple", "b": "banana"}
for k, v := range kvs {
fmt.Printf("%s -> %s\n", k, v)
}
}
四、集合 map
func mapDef() {
//創建map
goMap := make(map[string]string)
goMap["key1"] = "go1"
goMap["key2"] = "go2"
goMap["key3"] = "go3"
//創建map
goMap2 := map[string]string{"1": "1", "2": "2", "3": "3"}
for v := range goMap2 {
fmt.Println(v)
}
//遍歷map kv
for name := range goMap {
fmt.Println(name)
}
for k, v := range goMap {
fmt.Println("k:", k, "v:", v)
}
//刪除key
delete(goMap, "key1")
//遍歷 輸出key
for key := range goMap {
fmt.Println(key, "key is", goMap [ key ])
}
}
五、接口定義
import "fmt"
//定義接口
type VowelsFinder interface {
FindVowels() []rune
}
type MyString string
//實現接口
func (ms MyString) FindVowels() []rune {
var vowels []rune
for _, rune := range ms {
if rune == 'a' || rune == 'e' || rune == 'i' || rune == 'o' || rune == 'u' {
vowels = append(vowels, rune)
}
}
return vowels
}
func main() {
name := MyString("Sam Anderson") // 類型轉換
// 調用接口
var v VowelsFinder
v = name
fmt.Printf("Vowels are %c", v.FindVowels())
}
六、併發
goroutine是通過Go的runtime管理的一個線程管理器,通過關鍵字go就啓動了一個goroutine(一個線程)。
package main
import (
"fmt"
"runtime"
)
func say(s string) {
for i := 0; i < 5; i++ {
runtime.Gosched()
fmt.Println(s)
}
}
func main() {
go say("hello") //開一個新的Goroutines執行
say("world") //當前Goroutine執行
}
可以測試把main中的go關鍵字去掉zaiz在執行,此時的say("hello")和say("world")則開始串行執行。證明採用go關鍵字,確實新起了一個線程並行打印hello world。
七、反射
熟悉java的coder,反射肯定都爛熟於心了,go的反射也同理,不過要注意,go反射的字段一定是可讀寫的,比如下例,拿一個4的int常量值來反射修改成8,會報錯。而應該拿到x=4中x的內存地址進行修改。要修改的是變量內存指向8,而數值本身是4就是4,是不可寫的。
//反射
func reflectDef() {
x := 4
t := reflect.TypeOf(x)
v := reflect.ValueOf(x)
//v.SetInt(8) //報錯 反射的字段必須是可讀寫的
//改寫成
p:=reflect.ValueOf(&x) //拿到x變量的內存地址
v2:=p.Elem() //賦值給v2 再修改v2
v2.SetInt(8)
fmt.Println("反射獲取變量類型爲:",t)
fmt.Println(v)
fmt.Println("反射修改v的值爲:",v2)
}