GO 基礎語法(2)——指針結構體集合併發反射

一、指針

//指針 獲取對象、變量的內存地址
//取地址符是 &,放到一個變量前使用就會返回相應變量的內存地址。
//指針類型前面加上 * 號(前綴)來獲取指針所指向的內容
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)
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章