天天看點

Golang 語句、函數、可見性規則

目錄

      • 語句
        • if
        • switch
        • for
      • 函數
        • 函數的定義、使用
        • 傳回值名稱
        • 參數個數可變的函數
        • 函數作為參數
        • 函數閉包
      • 可見性規則

var a = 1

if a > 0 {
	fmt.Println("a>0")
} else if a == 0 {
	fmt.Println("a==0")
} else {
	fmt.Println("a<0")
}


//在條件中可以聲明指派,但不能用var,隻能用:=,聲明的變量的作用域是目前if語句中
if b := 1; b > 0 {
	fmt.Println("b>0")
} else if b == 0 {
	fmt.Println("b==0")
} else {
	fmt.Println("b<0")
}
           

func f1(a, b int, operator string) {
	switch operator {
	case "+":
		fmt.Printf("%d%s%d=%d\n", a, operator, b, a+b)
	case "-":
		fmt.Printf("%d%s%d=%d\n", a, operator, b, a-b)
	case "*":
		fmt.Printf("%d%s%d=%d\n", a, operator, b, a*b)
	case "/":
		fmt.Printf("%d%s%d=%d\n", a, operator, b, a/b)
	default:
		//panic(fmt.Sprintf("不支援的運算符:%s", operator))
		panic("不支援的運算符:" + operator)
	}
}


func f2(score int) {
	switch {
	case score >= 80 && score <= 100:
		fmt.Println("優秀")
	case score >= 60 && score < 80:
		fmt.Println("良好")
	case score >= 0 && score < 60:
		fmt.Println("不及格")
	default:
		//panic(fmt.Sprintf("不合法的分數值:%d", score))
		panic("不合法的分數值:" + strconv.Itoa(score))
	}
}
           
  • case會自動加上break,不用手動加
  • switch後可以有表達式,也可以沒有
  • case中可以寫條件,可以寫多個條件,作用類似于if語句

for i := 0; i < 10; i++ {
	fmt.Println(i)
}


arr := []string{"a", "b", "c", "d"}

//周遊數組,有2個變量時,第一個是下标,第二個是元素值
for index, value := range arr {
	fmt.Println(index, value)
}

//如果不使用其中某個變量,可寫成_
for _, value := range arr {
	fmt.Println(value)
}

//如果隻有一個變量,則為下标
for index := range arr {
	fmt.Println(index)
}


//初始值、循環條件、變量變化表達式均可預設,全部預設時為無限循環
for {
	fmt.Println("ok")
}
           
  • golang中沒有while循環,while循環可以轉換為for,使用for即可
  • 内建容器都可以用for range周遊

  • golang的參數、變量聲明都是變量名在前,類型在後
  • golang函數的傳回值類型放在最後,形參沒有預設值
//無傳回值時不用寫傳回值類型
func f1(name string, age int) {
	fmt.Printf("執行f1,name=%s,age=%d\n", name, age)
}


//如果參數類型相同,可以合寫成 參數名1,參數名2 類型
func f2(a, b int, operator string) int {
	switch operator {
	case "+":
		return a + b
	case "-":
		return a - b
	case "*":
		return a * b
	case "/":
		return a / b
	default:
		panic("不支援的運算符:" + operator)
	}
}


//可以有多個傳回值,傳回值類型放在()中
func f3(a, b int) (int, int) {
	return b, a
}


func main() {
	f1("chy", 20)

	result := f2(10, 20, "+")
	fmt.Printf("f2()傳回的值:%d\n", result)

	a, b := f3(10, 20)
	fmt.Printf("f3()傳回的值:%d\t%d\n", a, b)
}
           

/*
可以給傳回值起名字,這樣Ctrl+ALt+V補全時會使用對應的變量名來接收
不建議這樣做,到處都是變量名,看起來有些混亂,如果要用,盡量隻用在簡單的函數上
*/
func f1(a, b int) (sum, diff int) {
	return a + b, a - b
}

func main() {
	sum, diff := f1(100, 10)
	fmt.Println(sum, diff)
}
           

//參數個數可變的函數,使用數組接受參數
func sum(values ...int) int {
	sum := 0
	for _, value := range values {
		sum += value
	}
	return sum
}

func main() {
	sum := sum(1, 2, 3, 4)
	fmt.Println(sum)
}
           

//函數可以作為參數。此處oper代表函數名,func(int, int) int是函數原型
func apply(oper func(int, int) int, a, b int) int {
	return oper(a, b)
}

func main() {
	result := apply(func(a int, b int) int {
		return a + b
	}, 10, 20)
	fmt.Println(result)
}
           

閉包:傳回值是函數,傳回函數中使用的局部變量也會儲存在記憶體中

//func(int) int是函數原型,傳回值類型是這種類型的函數
func adder() func(int) int {
	sum := 0
	//傳回的函數中包含了變量sum,sum随傳回的函數一起被儲存在記憶體中
	return func(a int) int {
		sum += a
		return sum
	}
}

func main() {
	//用一個變量儲存addr()傳回的函數,可以把f做函數名來調用傳回的函數
	f := adder()
	for i := 1; i < 10; i++ {
		fmt.Printf("0+...+%d=%d\n", i, f(i))
	}
}
           
  • i=1時,第一次調用f(i),sum=0+1=1,sum=1随函數被儲存在記憶體中
  • i=2時,第二次調用f(i),sum=1+2=3 ,sum使用的是被儲存在記憶體中的值,不是初始值

與其它語言的辨別符命名規則不同,golang的辨別命名有特殊含義,辨別着可見性,不能随便大小寫。

如果常量名、變量名、結構體名、函數名等

  • 以小寫開頭,則隻在目前包中可見,可在目前中直接使用
  • 以大寫開頭,則是公共變量,在其它包中可見,可導入使用

假設有一個目錄D:/gopath/demo,GOPATH是D:/gopath,demo是項目根目錄,demo下有2個包:package1、main

package1

var Name = "chy"

func F() {
	fmt.Println("正在執行F()...")
}

//内部字段名也要大寫,不然不能通路、操作内部字段
type Node struct {
	Value     int
	Pre, Next *Node
}
           

main

import (
	"fmt"
	//導入時取GOPATH後面的路徑,直到包名
	"demo/package1"
)

func main() {
	//通過包名來引用
	fmt.Println(package1.Name)
	package1.F()

	head := package1.Node{Value: 10}
	fmt.Println(head.Value)
	fmt.Println(head.Pre)
}