ตัวแปรใน Go
ตัวแปรคือตำแหน่งเก็บสำหรับเก็บค่าหนึ่งค่า อนุญาตให้ค่าที่เก็บเปลี่ยนแปลงแบบไดนามิกในขณะรันไทม์ ทุกครั้งที่ประกาศตัวแปร จะจัดสรรบล็อกหน่วยความจำให้มันเพื่อเก็บค่าของประเภทที่ตรงกัน ไปที่ คู่มืออ้างอิง-ตัวแปร เพื่อดูรายละเอียดเพิ่มเติม
การประกาศ
ใน Go การประกาศประเภทอยู่ด้านหลัง การประกาศตัวแปรจะใช้คีย์เวิร์ด var รูปแบบคือ var ชื่อตัวแปร ชื่อประเภท กฎการตั้งชื่อตัวแปรต้องปฏิบัติตามกฎการตั้งชื่อตัวระบุ
var intNum int
var str string
var char byteเมื่อต้องการประกาศตัวแปรหลายตัวที่มีประเภทเดียวกัน สามารถเขียนประเภทเพียงครั้งเดียว
var numA, numB, numC intเมื่อต้องการประกาศตัวแปรหลายตัวที่มีประเภทต่างกัน สามารถใช้ () ห่อหุ้ม สามารถมี () หลายตัวได้
var (
name string
age int
address string
)
var (
school string
class int
)ตัวแปรหนึ่งหากเพียงประกาศ而不กำหนดค่า ค่าที่ตัวแปรเก็บคือค่าศูนย์ของประเภทที่ตรงกัน
การกำหนดค่า
การกำหนดค่าจะใช้ตัวดำเนินการ = เช่น
var name string
name = "jack"ยังสามารถกำหนดค่าโดยตรงเมื่อประกาศ
var name string = "jack"หรือแบบนี้ก็ได้
var name string
var age int
name, age = "jack", 1วิธีที่สองต้องระบุประเภททุกครั้ง สามารถใช้ syntactic sugar ที่ทางการมีให้ คือ การเริ่มต้นตัวแปรสั้น สามารถละเว้นคีย์เวิร์ด var และประเภทด้านหลัง ให้คอมไพเลอร์อนุมัติประเภทเอง
name := "jack" // ตัวแปรประเภทสตริงแม้ว่าจะไม่ต้องระบุประเภทได้ แต่ในการกำหนดค่าในภายหลัง ประเภทต้อง保持一致 โค้ดแบบนี้ไม่สามารถผ่านการคอมไพล์ได้
a := 1
a = "1"สิ่งที่ควรระวังอีกอย่างคือ การเริ่มต้นตัวแปรสั้นไม่สามารถใช้ nil ได้ เพราะ nil ไม่属于ประเภทใดๆ คอมไพเลอร์ไม่สามารถอนุมัติประเภทได้
name := nil // ไม่สามารถผ่านการคอมไพล์การประกาศตัวแปรสั้นสามารถเริ่มต้นเป็นชุดได้
name, age := "jack", 1วิธีการประกาศตัวแปรสั้นไม่สามารถใช้กับตัวแปรที่มีอยู่แล้วได้ เช่น
// ตัวอย่างผิด
var a int
a := 1
// ตัวอย่างผิด
a := 1
a := 2แต่มีสถานการณ์หนึ่งข้อยกเว้น นั่นคือเมื่อกำหนดค่าตัวแปรเก่า的同时ประกาศตัวแปรใหม่หนึ่งตัว เช่น
a := 1
a, b := 2, 2โค้ดแบบนี้สามารถผ่านการคอมไพล์ได้ ตัวแปร a ถูกกำหนดค่าใหม่ ส่วน b เป็นตัวแปรที่ประกาศใหม่
ในภาษา Go มีกฎหนึ่งข้อ นั่นคือตัวแปรทั้งหมดในฟังก์ชันต้องถูกใช้ เช่นโค้ดด้านล่างเพียงประกาศตัวแปร แต่ไม่ได้ใช้มัน
func main() {
a := 1
}เช่นนี้เมื่อคอมไพล์จะรายงานข้อผิดพลาด บอกคุณว่าตัวแปรนี้ประกาศแล้วแต่ไม่ได้ใช้
a declared and not usedกฎข้อนี้ใช้กับตัวแปรในฟังก์ชันเท่านั้น สำหรับตัวแปรระดับแพ็กเกจนอกฟังก์ชันไม่มีข้อจำกัดนี้ โค้ดด้านล่างสามารถผ่านการคอมไพล์ได้
var a = 1
func main() {
}ไม่ระบุชื่อ
ใช้อันเดอร์สกอร์สามารถแสดงว่าไม่ต้องการตัวแปรหนึ่งตัว
Open(name string) (*File, error)เช่นฟังก์ชัน os.Open มีค่าส่งคืนสองค่า เราต้องการเพียงค่าแรก ไม่ต้องการค่าที่สอง สามารถเขียนแบบนี้
file, _ := os.Open("readme.txt")ตัวแปรที่ไม่ได้ใช้ไม่สามารถผ่านการคอมไพล์ได้ เมื่อคุณไม่ต้องการตัวแปรหนึ่งตัว ก็สามารถใช้อันเดอร์สกอร์ _ แทนได้
การสลับ
ใน Go หากต้องการสลับค่าของตัวแปรสองตัว ไม่ต้องใช้พอยน์เตอร์ สามารถใช้ตัวดำเนินการกำหนดค่า进行สลับโดยตรง ไวยากรณ์ดูง่ายมาก ตัวอย่างดังนี้
num1, num2 := 25, 36
num1, num2 = num2, num1สามตัวแปรก็เช่นเดียวกัน
num1, num2, num3 := 25, 36, 49
num1, num2, num3 = num3, num2, num1คิดโค้ดส่วนนี้ นี่คือโค้ด一小段สำหรับคำนวณลำดับฟีโบนัชชี ค่าของสามตัวแปรหลังการคำนวณคืออะไร
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 ดำเนินการกำหนดค่าตัวแปรหลายตัว ลำดับของมันคือคำนวณค่าก่อนแล้วค่อยกำหนดค่า ไม่ใช่คำนวณจากซ้ายไปขวา
a, b, c = b, c, a+bคุณอาจคิดว่ามันจะถูก展开เป็นโค้ดส่วนนี้
a = b
b = c
c = a + bแต่ที่จริงแล้วมันจะคำนวณค่าของตัวแปร a, b, c ทั้งสามให้เรียบร้อยก่อนแล้วค่อยกำหนดค่าให้พวกมัน ก็เหมือนกับโค้ดส่วนนี้
a, b, c = 1, 1, 0+1เมื่อเกี่ยวข้องกับการเรียกฟังก์ชัน เอฟเฟกต์นี้จะชัดเจนยิ่งขึ้น เรามีฟังก์ชัน sum หนึ่งฟังก์ชันสามารถคำนวณค่าส่งคืนของตัวเลขสองตัว
func sum(a, b int) int {
return a + b
}ใช้ฟังก์ชัน进行บวกสองจำนวน
a, b, c := 0, 1, 1
a, b, c = b, c, sum(a, b)ผลลัพธ์ไม่เปลี่ยนแปลง เมื่อคำนวณค่าส่งคืนของฟังก์ชัน sum พารามิเตอร์เข้าของมันยังคงเป็น 0 และ 1
1 1 1ดังนั้นโค้ดควรเขียนแยกแบบนี้
a, b = b, c
c = a + bการเปรียบเทียบ
การเปรียบเทียบระหว่างตัวแปรมีเงื่อนไขใหญ่หนึ่งข้อ นั่นคือประเภทของพวกมันต้องเหมือนกัน ในภาษา Go ไม่มีการแปลงประเภทโดยนัย โค้ดแบบนี้ไม่สามารถผ่านการคอมไพล์ได้
func main() {
var a uint64
var b int64
fmt.Println(a == b)
}คอมไพเลอร์จะบอกคุณว่าประเภทของทั้งสองไม่เหมือนกัน
invalid operation: a == b (mismatched types uint64 and int64)ดังนั้นต้องใช้การแปลงประเภทอย่างชัดเจน
func main() {
var a uint64
var b int64
fmt.Println(int64(a) == b)
}ก่อนมี generics ฟังก์ชันในตัว min, max ที่ Go มีให้ตอนแรกรองรับเพียงจำนวนจริง ถึงเวอร์ชัน 1.21 Go จึงเขียนฟังก์ชันในตัวสองฟังก์ชันนี้ใหม่ด้วย generics ตอนนี้สามารถใช้ฟังก์ชัน min เปรียบเทียบค่าต่ำสุดได้
minVal := min(1, 2, -1, 1.2)ใช้ฟังก์ชัน max เปรียบเทียบค่าสูงสุด
maxVal := max(100, 22, -1, 1.12)พารามิเตอร์ของพวกมันรองรับประเภทที่เปรียบเทียบได้ทั้งหมด ประเภทที่เปรียบเทียบได้ใน Go มี
- บูลีน
- ตัวเลข
- สตริง
- พอยน์เตอร์
- แชนเนล (รองรับเพียงการตัดสินว่าเท่ากันหรือไม่)
- อาร์เรย์ที่องค์ประกอบเป็นประเภทที่เปรียบเทียบได้ (สไลซ์ไม่สามารถเปรียบเทียบได้) (รองรับเพียงการตัดสินว่าเท่ากันหรือไม่) (รองรับเพียงการเปรียบเทียบระหว่างอาร์เรย์ที่มีความยาวเท่ากัน เพราะความยาวอาร์เรย์ก็เป็นส่วนหนึ่งของประเภทด้วย และประเภทต่างกันไม่สามารถเปรียบเทียบได้)
- สตรักเจอร์ที่ประเภทฟิลด์ทั้งหมดเป็นประเภทที่เปรียบเทียบได้ (รองรับเพียงการตัดสินว่าเท่ากันหรือไม่)
นอกจากนี้还可以通过นำเข้าไลบรารีมาตรฐาน cmp เพื่อตัดสิน แต่รองรับเพียงพารามิเตอร์ประเภทที่มีลำดับ ใน Go ประเภทที่มีลำดับในตัวมีเพียงตัวเลขและสตริง
import "cmp"
func main() {
cmp.Compare(1, 2)
cmp.Less(1, 2)
}บล็อกโค้ด
ภายในฟังก์ชัน สามารถใช้วงเล็บปีกกาสร้างบล็อกโค้ดหนึ่งบล็อก ขอบเขตตัวแปรระหว่างบล็อกโค้ดเป็นอิสระต่อกัน เช่นโค้ดด้านล่าง
func main() {
a := 1
{
a := 2
fmt.Println(a)
}
{
a := 3
fmt.Println(a)
}
fmt.Println(a)
}เอาต์พุตของมันคือ
2
3
1ตัวแปรระหว่างบล็อกกับบล็อกเป็นอิสระต่อกัน ไม่ถูกรบกวน ไม่สามารถเข้าถึงได้ แต่จะได้รับผลกระทบจากบล็อกพ่อ
func main() {
a := 1
{
a := 2
fmt.Println(a)
}
{
fmt.Println(a)
}
fmt.Println(a)
}เอาต์พุตของมันคือ
2
1
1