Skip to content

ตัวแปรใน Go

ตัวแปรคือตำแหน่งเก็บสำหรับเก็บค่าหนึ่งค่า อนุญาตให้ค่าที่เก็บเปลี่ยนแปลงแบบไดนามิกในขณะรันไทม์ ทุกครั้งที่ประกาศตัวแปร จะจัดสรรบล็อกหน่วยความจำให้มันเพื่อเก็บค่าของประเภทที่ตรงกัน ไปที่ คู่มืออ้างอิง-ตัวแปร เพื่อดูรายละเอียดเพิ่มเติม

การประกาศ

ใน Go การประกาศประเภทอยู่ด้านหลัง การประกาศตัวแปรจะใช้คีย์เวิร์ด var รูปแบบคือ var ชื่อตัวแปร ชื่อประเภท กฎการตั้งชื่อตัวแปรต้องปฏิบัติตามกฎการตั้งชื่อตัวระบุ

go
var intNum int
var str string
var char byte

เมื่อต้องการประกาศตัวแปรหลายตัวที่มีประเภทเดียวกัน สามารถเขียนประเภทเพียงครั้งเดียว

go
var numA, numB, numC int

เมื่อต้องการประกาศตัวแปรหลายตัวที่มีประเภทต่างกัน สามารถใช้ () ห่อหุ้ม สามารถมี () หลายตัวได้

go
var (
  name    string
  age     int
  address string
)

var (
  school string
  class int
)

ตัวแปรหนึ่งหากเพียงประกาศ而不กำหนดค่า ค่าที่ตัวแปรเก็บคือค่าศูนย์ของประเภทที่ตรงกัน

การกำหนดค่า

การกำหนดค่าจะใช้ตัวดำเนินการ = เช่น

go
var name string
name = "jack"

ยังสามารถกำหนดค่าโดยตรงเมื่อประกาศ

go
var name string = "jack"

หรือแบบนี้ก็ได้

go
var name string
var age int
name, age = "jack", 1

วิธีที่สองต้องระบุประเภททุกครั้ง สามารถใช้ syntactic sugar ที่ทางการมีให้ คือ การเริ่มต้นตัวแปรสั้น สามารถละเว้นคีย์เวิร์ด var และประเภทด้านหลัง ให้คอมไพเลอร์อนุมัติประเภทเอง

go
name := "jack" // ตัวแปรประเภทสตริง

แม้ว่าจะไม่ต้องระบุประเภทได้ แต่ในการกำหนดค่าในภายหลัง ประเภทต้อง保持一致 โค้ดแบบนี้ไม่สามารถผ่านการคอมไพล์ได้

a := 1
a = "1"

สิ่งที่ควรระวังอีกอย่างคือ การเริ่มต้นตัวแปรสั้นไม่สามารถใช้ nil ได้ เพราะ nil ไม่属于ประเภทใดๆ คอมไพเลอร์ไม่สามารถอนุมัติประเภทได้

go
name := nil // ไม่สามารถผ่านการคอมไพล์

การประกาศตัวแปรสั้นสามารถเริ่มต้นเป็นชุดได้

go
name, age := "jack", 1

วิธีการประกาศตัวแปรสั้นไม่สามารถใช้กับตัวแปรที่มีอยู่แล้วได้ เช่น

go
// ตัวอย่างผิด
var a int
a := 1

// ตัวอย่างผิด
a := 1
a := 2

แต่มีสถานการณ์หนึ่งข้อยกเว้น นั่นคือเมื่อกำหนดค่าตัวแปรเก่า的同时ประกาศตัวแปรใหม่หนึ่งตัว เช่น

go
a := 1
a, b := 2, 2

โค้ดแบบนี้สามารถผ่านการคอมไพล์ได้ ตัวแปร a ถูกกำหนดค่าใหม่ ส่วน b เป็นตัวแปรที่ประกาศใหม่

ในภาษา Go มีกฎหนึ่งข้อ นั่นคือตัวแปรทั้งหมดในฟังก์ชันต้องถูกใช้ เช่นโค้ดด้านล่างเพียงประกาศตัวแปร แต่ไม่ได้ใช้มัน

go
func main() {
  a := 1
}

เช่นนี้เมื่อคอมไพล์จะรายงานข้อผิดพลาด บอกคุณว่าตัวแปรนี้ประกาศแล้วแต่ไม่ได้ใช้

a declared and not used

กฎข้อนี้ใช้กับตัวแปรในฟังก์ชันเท่านั้น สำหรับตัวแปรระดับแพ็กเกจนอกฟังก์ชันไม่มีข้อจำกัดนี้ โค้ดด้านล่างสามารถผ่านการคอมไพล์ได้

go
var a = 1

func main() {

}

ไม่ระบุชื่อ

ใช้อันเดอร์สกอร์สามารถแสดงว่าไม่ต้องการตัวแปรหนึ่งตัว

go
Open(name string) (*File, error)

เช่นฟังก์ชัน os.Open มีค่าส่งคืนสองค่า เราต้องการเพียงค่าแรก ไม่ต้องการค่าที่สอง สามารถเขียนแบบนี้

go
file, _ := os.Open("readme.txt")

ตัวแปรที่ไม่ได้ใช้ไม่สามารถผ่านการคอมไพล์ได้ เมื่อคุณไม่ต้องการตัวแปรหนึ่งตัว ก็สามารถใช้อันเดอร์สกอร์ _ แทนได้

การสลับ

ใน Go หากต้องการสลับค่าของตัวแปรสองตัว ไม่ต้องใช้พอยน์เตอร์ สามารถใช้ตัวดำเนินการกำหนดค่า进行สลับโดยตรง ไวยากรณ์ดูง่ายมาก ตัวอย่างดังนี้

go
num1, num2 := 25, 36
num1, num2 = num2, num1

สามตัวแปรก็เช่นเดียวกัน

go
num1, num2, num3 := 25, 36, 49
num1, num2, num3  = num3, num2, num1

คิดโค้ดส่วนนี้ นี่คือโค้ด一小段สำหรับคำนวณลำดับฟีโบนัชชี ค่าของสามตัวแปรหลังการคำนวณคืออะไร

go
a, b, c := 0, 1, 1
a, b, c = b, c, a+b

คำตอบคือ

1 1 1

คุณอาจสงสัยว่าทำไมไม่ใช่

1 1 2

明明 a ถูกกำหนดค่าของ b แล้ว ทำไมผลลัพธ์ของ a+b ยังเป็น 1? เมื่อ Go ดำเนินการกำหนดค่าตัวแปรหลายตัว ลำดับของมันคือคำนวณค่าก่อนแล้วค่อยกำหนดค่า ไม่ใช่คำนวณจากซ้ายไปขวา

go
a, b, c = b, c, a+b

คุณอาจคิดว่ามันจะถูก展开เป็นโค้ดส่วนนี้

go
a = b
b = c
c = a + b

แต่ที่จริงแล้วมันจะคำนวณค่าของตัวแปร a, b, c ทั้งสามให้เรียบร้อยก่อนแล้วค่อยกำหนดค่าให้พวกมัน ก็เหมือนกับโค้ดส่วนนี้

go
a, b, c = 1, 1, 0+1

เมื่อเกี่ยวข้องกับการเรียกฟังก์ชัน เอฟเฟกต์นี้จะชัดเจนยิ่งขึ้น เรามีฟังก์ชัน sum หนึ่งฟังก์ชันสามารถคำนวณค่าส่งคืนของตัวเลขสองตัว

go
func sum(a, b int) int {
  return a + b
}

ใช้ฟังก์ชัน进行บวกสองจำนวน

go
a, b, c := 0, 1, 1
a, b, c = b, c, sum(a, b)

ผลลัพธ์ไม่เปลี่ยนแปลง เมื่อคำนวณค่าส่งคืนของฟังก์ชัน sum พารามิเตอร์เข้าของมันยังคงเป็น 0 และ 1

1 1 1

ดังนั้นโค้ดควรเขียนแยกแบบนี้

go
a, b = b, c
c = a + b

การเปรียบเทียบ

การเปรียบเทียบระหว่างตัวแปรมีเงื่อนไขใหญ่หนึ่งข้อ นั่นคือประเภทของพวกมันต้องเหมือนกัน ในภาษา Go ไม่มีการแปลงประเภทโดยนัย โค้ดแบบนี้ไม่สามารถผ่านการคอมไพล์ได้

go
func main() {
  var a uint64
  var b int64
  fmt.Println(a == b)
}

คอมไพเลอร์จะบอกคุณว่าประเภทของทั้งสองไม่เหมือนกัน

invalid operation: a == b (mismatched types uint64 and int64)

ดังนั้นต้องใช้การแปลงประเภทอย่างชัดเจน

go
func main() {
  var a uint64
  var b int64
  fmt.Println(int64(a) == b)
}

ก่อนมี generics ฟังก์ชันในตัว min, max ที่ Go มีให้ตอนแรกรองรับเพียงจำนวนจริง ถึงเวอร์ชัน 1.21 Go จึงเขียนฟังก์ชันในตัวสองฟังก์ชันนี้ใหม่ด้วย generics ตอนนี้สามารถใช้ฟังก์ชัน min เปรียบเทียบค่าต่ำสุดได้

go
minVal := min(1, 2, -1, 1.2)

ใช้ฟังก์ชัน max เปรียบเทียบค่าสูงสุด

go
maxVal := max(100, 22, -1, 1.12)

พารามิเตอร์ของพวกมันรองรับประเภทที่เปรียบเทียบได้ทั้งหมด ประเภทที่เปรียบเทียบได้ใน Go มี

  • บูลีน
  • ตัวเลข
  • สตริง
  • พอยน์เตอร์
  • แชนเนล (รองรับเพียงการตัดสินว่าเท่ากันหรือไม่)
  • อาร์เรย์ที่องค์ประกอบเป็นประเภทที่เปรียบเทียบได้ (สไลซ์ไม่สามารถเปรียบเทียบได้) (รองรับเพียงการตัดสินว่าเท่ากันหรือไม่) (รองรับเพียงการเปรียบเทียบระหว่างอาร์เรย์ที่มีความยาวเท่ากัน เพราะความยาวอาร์เรย์ก็เป็นส่วนหนึ่งของประเภทด้วย และประเภทต่างกันไม่สามารถเปรียบเทียบได้)
  • สตรักเจอร์ที่ประเภทฟิลด์ทั้งหมดเป็นประเภทที่เปรียบเทียบได้ (รองรับเพียงการตัดสินว่าเท่ากันหรือไม่)

นอกจากนี้还可以通过นำเข้าไลบรารีมาตรฐาน cmp เพื่อตัดสิน แต่รองรับเพียงพารามิเตอร์ประเภทที่มีลำดับ ใน Go ประเภทที่มีลำดับในตัวมีเพียงตัวเลขและสตริง

go
import "cmp"

func main() {
  cmp.Compare(1, 2)
  cmp.Less(1, 2)
}

บล็อกโค้ด

ภายในฟังก์ชัน สามารถใช้วงเล็บปีกกาสร้างบล็อกโค้ดหนึ่งบล็อก ขอบเขตตัวแปรระหว่างบล็อกโค้ดเป็นอิสระต่อกัน เช่นโค้ดด้านล่าง

go
func main() {
  a := 1

  {
    a := 2
    fmt.Println(a)
  }

  {
    a := 3
    fmt.Println(a)
  }
  fmt.Println(a)
}

เอาต์พุตของมันคือ

2
3
1

ตัวแปรระหว่างบล็อกกับบล็อกเป็นอิสระต่อกัน ไม่ถูกรบกวน ไม่สามารถเข้าถึงได้ แต่จะได้รับผลกระทบจากบล็อกพ่อ

go
func main() {
  a := 1

  {
    a := 2
    fmt.Println(a)
  }

  {
    fmt.Println(a)
  }
  fmt.Println(a)
}

เอาต์พุตของมันคือ

2
1
1

Golang by www.golangdev.cn edit