golang常用手冊:指標、結構體

pc859107393發表於2017-12-22

簽名我們瞭解了一些golang的基礎知識,可以明確的發現golang和c語言很是類似,那麼看到這裡,你可能更加震驚,這可能就是個新時代的c語言。

指標

變數是一種使用方便的佔位符,用於引用計算機記憶體地址。 Go 語言的取地址符是 &,放到一個變數前使用就會返回相應變數的記憶體地址。

示例程式碼如下:

package main

import "fmt"

func main() {
   var a int = 10   

   fmt.Printf("變數的地址: %x\n", &a  )
}
複製程式碼

輸出結果如下,可能這裡不同的電腦有一些不同的輸出結果:

變數的地址: c420014058
複製程式碼

指標的概念是:指向任何一個值的記憶體地址,是記憶體地址的編號。重點:

  • 是go中基本資料型別
  • 代表記憶體地址
  • 可以指向任意資料的地址
  • 不同資料型別的指標需要不同的資料型別和指標符號組合來表示

我們來看看簡單的一些例項:

//指標申明格式
// var var_name *var-type
// var-type 為指標型別,var_name 為指標變數名,* 號用於指定變數是作為一個指標。

var ip *int        /* 指向整型*/
var fp *float32    /* 指向浮點型 */

複製程式碼

指標和其他型別的變數一樣,我們需要申明和賦值後才能使用,看看下面的demo:

package main

import "fmt"

func main() {

	var a int = 20    /* 宣告實際變數 */

	var aPointer *int /* 宣告指標變數 */

	aPointer = &a /* 指標變數的儲存地址 */

	fmt.Printf("a 變數的地址是: %x\n", &a)

	/* 指標變數的儲存地址 */
	fmt.Printf("aPointer 變數儲存的指標地址: %x\n", aPointer)

	/* 使用指標訪問值 */
	fmt.Printf("*aPointer 變數的值: %d\n", *aPointer)
}
複製程式碼

輸出結果如下(不同電腦可能實際地址不同):

a 變數的地址是: c420014050
aPointer 變數儲存的指標地址: c420014050
*aPointer 變數的值: 20
複製程式碼

其實關於指標更加詳盡的用法可以看看大學c語言教材,以及資料結構c語言版。

空指標

當一個指標被定義後沒有分配到任何變數時,它的值為 nil。

nil 指標也稱為空指標。

nil在概念上和其它語言的null、None、nil、NULL一樣,都指代零值或空值。

一個指標變數通常縮寫為 ptr。

注意,指標還有以下操作:

  • 指標陣列(核心是陣列和指標)
  • 多級指標(指向指標的指標)
  • 函式的指標引數

我們來看看下面的例子:

package main

import "fmt"

func main() {

	var a int = 20 /* 宣告實際變數 */

	var aPointer *int /* 宣告指標變數 */

	aPointer = &a /* 指標變數的儲存地址 */

	fmt.Printf("a 變數的地址是: %x\n", &a)

	/* 指標變數的儲存地址 */
	fmt.Printf("aPointer 變數儲存的指標地址: %x\n", aPointer)

	/* 使用指標訪問值 */
	fmt.Printf("*aPointer 變數的值: %d\n", *aPointer)

	b := 35
	bPointer := &b

	fmt.Printf("a = %d ,b = %d \n", a, b)
	fmt.Printf("aPointer = %x ,bPointer = %x \n", aPointer, bPointer)

	swap(aPointer, bPointer)

	fmt.Println("交換後的結果")
	fmt.Printf("a = %d ,b = %d \n", a, b)
	fmt.Printf("aPointer = %x ,bPointer = %x \n", aPointer, bPointer)

	pBPtr := &bPointer

	fmt.Printf("pBPtr = %x ,*pBPtr = %x  ,**pBPtr = %x \n", pBPtr, *pBPtr, **pBPtr)

}

func swap(a, b *int) {
	tmp := *a

	*a = *b

	*b = tmp
}

複製程式碼

輸出的結果是hi:

a 變數的地址是: c420014050
aPointer 變數儲存的指標地址: c420014050
*aPointer 變數的值: 20
a = 20 ,b = 35 
aPointer = c420014050 ,bPointer = c420014060 
交換後的結果
a = 35 ,b = 20 
aPointer = c420014050 ,bPointer = c420014060 
pBPtr = c42000c030 ,*pBPtr = c420014060  ,**pBPtr = 14 
複製程式碼

在上面的例子中,我們可以明顯的看到a、b的值在交換後發生了變化,但是aPointer和bPointer的值並沒有發生變化。

在交換函式中,我們把a、b的值通過指標操作的方式直接更改了,但是aPointer和bPointer是指向了a、b的地址,我們並沒有改變他們,則有aPointer和bPointer值沒有變化。

接著我們申明並且初始化了一個二級指標pBPtr,他的值是bPointer這個指標變數的地址,接著*pBPtr的值是bPointer指向的地址也即是b的地址,所以**pBPtr的值是b的值。

結構體

結構體,和我們在c語言中遇到的一樣,用來將不同資料(無論資料型別是否相同)組裝在一起。在其他的面嚮物件語言中,比如說java,我們習慣來寫bean物件,如下:

//在java中建立Person實體
class Person implements Serializable{
    private String name;
    private Integer age;
}
複製程式碼

那麼我們在go中如何操作呢?

type Person struct {
	name string
	age  int
}
複製程式碼

當然,我們不妨看看具體demo:

package main

import "fmt"

type Person struct {
	name string
	age  int
}

//這裡是方法,輸入Person的方法
func (person Person) logPerson() {
	fmt.Printf("%s,年齡:%d", person.name, person.age)
}

func main() {
	var aPerson Person

	aPerson.name = "go語言"
	aPerson.age = 8
	aPerson.logPerson()

}
複製程式碼

在上面的程式碼中,我們使用了一些知識點:

  • 變數,申明和賦值
  • 包名、導包、主函式
  • 函式、方法
  • 結構體

我們再主函式中,申明瞭aPerson變數,且資料型別是結構體Person。然後我們針對結構體的具體屬性進行了初始化,然後呼叫結構體自身的方法實現了列印Person的相關資訊。

當然結構體有一些以下操作:

  • 屬性訪問,結構體變數名.屬性名
  • 類似基本資料型別的使用方法(申明變數、函式引數、指標等)

下面的demo基本闡述了結構體的常規用法:

package main

import "fmt"

type Person struct {
	name string
	age  int
}

func (person Person) logPerson() {
	fmt.Printf("%s,年齡:%d \n", person.name, person.age)
}

func printPersonByPointer(person *Person) {
	fmt.Printf("%s,年齡:%d \n", person.name, person.age)
}

func printPerson(person Person) {
	fmt.Printf("%s,年齡:%d \n", person.name, person.age)
}

func main() {
	var aPerson Person

	aPerson.name = "go語言"
	aPerson.age = 8
	aPerson.logPerson()

	printPersonByPointer(&aPerson)
	
	printPerson(aPerson)
}

複製程式碼

注意:在go語言中,不支援函式過載

總結

go語言和c語言又很多類似的地方。指標和結構體都是c語言中類似的概念。

  • 指標支援任意資料型別的操作,指標申明格式為:var *name dataType
  • 指標儲存記憶體地址,&是取變數的地址,*是取指標指向記憶體的值
  • 多級指標的層級
  • 結構體可以稱之為擴充套件資料型別或包裝資料型別
  • 結構體用於定義非基本資料型別
  • 結構體的基本操作(屬性讀寫、函式引數、結構體指標)

如果你認可我所做的事情,並且認為我做的事對你有一定的幫助,希望你也能打賞我一杯咖啡,謝謝。

支付寶捐贈

相關文章