ตัวอย่าง Golang Generics

Tawxyang Golang Generics



คุณสมบัติทั่วไปของ Golang ทำให้สามารถสร้างรหัสที่ใช้ซ้ำได้ซึ่งปลอดภัยต่อประเภทและเข้ากันได้กับประเภทต่างๆ มากมาย โชคดีที่การเพิ่ม generics ให้กับ Go เปิดช่องทางใหม่สำหรับการใช้โค้ดซ้ำและความยืดหยุ่น Golang เวอร์ชันล่าสุดมาพร้อมกับการสนับสนุนที่คาดหวังสูงสำหรับยาชื่อสามัญ

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

ตัวอย่างที่ 1: การใช้ฟังก์ชัน Golang Generic

หนึ่งในกรณีการใช้งานหลักสำหรับยาชื่อสามัญคือการสร้างฟังก์ชันที่สามารถทำงานในประเภทที่แตกต่างกันได้ ต่อไปนี้เป็นตัวอย่างหนึ่งที่ใช้ฟังก์ชันเส้นรอบวงทั่วไป







บรรจุุภัณฑ์ หลัก
นำเข้า 'เอฟเอ็มที'
ฟังก์ชั่น เส้นรอบวง [ นานาชาติ | ลอย32 ]( รัศมี r ) {
:= 3 * 2 * รัศมี
เอฟเอ็มที . พิมพ์ ( 'เส้นรอบวงทั่วไปคือ: ' , )
}
ฟังก์ชั่น หลัก () {
เคยเป็น r1 นานาชาติ = 7
เคยเป็น r2 ลอย32 = 7 . 5
เส้นรอบวง ( r1 )
เส้นรอบวง ( r2 )
}

ที่จุดเริ่มต้นของรหัสก่อนหน้า บรรทัดนำเข้าแพ็คเกจ 'fmt' ซึ่งมีฟังก์ชันสำหรับ I/O ที่จัดรูปแบบ รวมถึงการพิมพ์เอาต์พุตไปยังคอนโซล จากนั้น เรากำหนดฟังก์ชันทั่วไปชื่อ 'เส้นรอบวง' ซึ่งใช้รัศมีพารามิเตอร์ของประเภททั่วไป 'r' ซึ่งสามารถเป็นได้ทั้ง 'int' หรือ 'float32' ภายในฟังก์ชัน จะคำนวณเส้นรอบวงโดยการคูณรัศมีด้วยค่าคงที่ของ '3' แล้วคูณด้วย '2' สุดท้าย พิมพ์เส้นรอบวงที่คำนวณได้โดยใช้ “fmt.Println”



ต่อไป เรามีฟังก์ชันหลักที่ตัวแปรสองตัวคือ r1 และ r2 ถูกประกาศและกำหนดค่าด้วยค่า 7 และ 7.5 ตามลำดับ หลังจากนั้น ฟังก์ชัน “circumference” จะถูกเรียกใช้สองครั้ง โดยส่ง r1 และ r2 เป็นอาร์กิวเมนต์



ผลลัพธ์จะแสดงการคำนวณโดยการพิมพ์เส้นรอบวงของวงกลมดังต่อไปนี้:





ตัวอย่างที่ 2:  การใช้ Golang Generic Interface

ยิ่งไปกว่านั้น Golang generics ยังช่วยเหลือเราด้วยอินเทอร์เฟซของพวกเขา อินเทอร์เฟซใน Go เป็นเครื่องมือสำคัญในการอำนวยความสะดวกในการใช้รหัสซ้ำและความหลากหลาย ด้วยการทำให้สามารถทำงานกับหลายประเภทได้ ยาชื่อสามัญจึงเพิ่มพลังของอินเทอร์เฟซ ต่อไปนี้คือซอร์สโค้ดของอินเตอร์เฟส Golang generics:



บรรจุุภัณฑ์ หลัก
นำเข้า 'เอฟเอ็มที'
พิมพ์ เอ็มพีเอจ อินเตอร์เฟซ {
int64 | int32 | ลอย32 | float64
}
ฟังก์ชั่น ใหม่GenericFunc [ อายุ อายุ ]( emp_Age อายุ ) {
วาล := นานาชาติ ( emp_อายุ ) + 1
เอฟเอ็มที . พิมพ์ ( วาล )
}
ฟังก์ชั่น หลัก () {
เอฟเอ็มที . พิมพ์ ( “อายุพนักงาน” )
เคยเป็น อายุ1 int64 = 24
เคยเป็น อายุ2 float64 = 25 . 5
ใหม่GenericFunc ( อายุ1 )
ใหม่GenericFunc ( อายุ2 )
}

ในซอร์สโค้ดก่อนหน้านี้ เราได้กำหนดอินเทอร์เฟซชื่อ 'EmpAge' ซึ่งระบุประเภทที่เป็นไปได้สำหรับอายุของพนักงาน อินเทอร์เฟซประกอบด้วยประเภท int64, int32, float32 และ float64 อินเทอร์เฟซนี้อนุญาตให้ฟังก์ชัน 'ทั่วไป' ยอมรับประเภทเหล่านี้เป็นอาร์กิวเมนต์ หลังจากนั้น เราใช้ฟังก์ชันทั่วไปชื่อ newGenericFunc ซึ่งใช้พารามิเตอร์ emp_Age ของประเภทอายุทั่วไป ซึ่งสามารถเป็นประเภทใดก็ได้ที่ตรงกับอินเทอร์เฟซ EmpAge ภายในฟังก์ชัน จะแปลง emp_Age เป็น int และเพิ่มทีละ 1 ดังที่แสดง

ต่อไป เราจะประกาศตัวแปรสองตัวคือ Age1 และ Age2 และกำหนดค่า 24 และ 25.5 ตามลำดับในฟังก์ชันหลัก หลังจากนั้น Age1 และ Age2 จะถูกส่งผ่านเป็นพารามิเตอร์ไปยังฟังก์ชัน newGenericFunc ซึ่งผ่านการดำเนินการสองครั้ง ด้วยเหตุนี้ อายุจะเพิ่มขึ้น 1 และสร้างค่าที่อัปเดต

ผลลัพธ์ที่ได้ต่อไปนี้คืออายุจากฟังก์ชันทั่วไปที่ใช้อินเทอร์เฟซ:

ตัวอย่างที่ 3: การใช้โครงสร้างข้อมูลทั่วไปของ Golang

นอกจากนี้ Go generics ยังช่วยให้เราสามารถสร้างโครงสร้างข้อมูลทั่วไป เช่น สแต็ค คิว และลิงค์ลิสต์ พิจารณาการนำสแต็คทั่วไปไปใช้ในสิ่งต่อไปนี้:

นำเข้า 'เอฟเอ็มที'
พิมพ์ ซ้อนกัน [ T ใด ๆ ] []
ฟังก์ชั่น ( เซนต์ * ซ้อนกัน [ ]) ดัน ( รายการ T ) {
เซนต์ = ผนวก ( * เซนต์ , รายการ )
}
ฟังก์ชั่น ( เซนต์ * ซ้อนกัน [ ]) โผล่ () {
ถ้า เท่านั้น ( * เซนต์ ) == 0 {
ตื่นตกใจ ( 'ไม่มีอะไรในกอง' )
}
ดัชนี := เท่านั้น ( * เซนต์ ) - 1
รายการ := ( * เซนต์ )[ ดัชนี ]
* เซนต์ = ( * เซนต์ ) [: ดัชนี ]
กลับ รายการ
}
ฟังก์ชั่น หลัก () {
ซ้อนกัน := ใหม่ ( ซ้อนกัน [ นานาชาติ ])
ซ้อนกัน . ดัน ( 1 )
ซ้อนกัน . ดัน ( 2 )
ซ้อนกัน . ดัน ( 3 )
เอฟเอ็มที . พิมพ์ ( ซ้อนกัน . โผล่ ())
เอฟเอ็มที . พิมพ์ ( ซ้อนกัน . โผล่ ())
เอฟเอ็มที . พิมพ์ ( ซ้อนกัน . โผล่ ())
}

ในโค้ดก่อนหน้านี้ มีการกำหนดประเภททั่วไปที่ชื่อว่า “สแต็ก” ซึ่งแสดงถึงสแต็ก ตัวยึดตำแหน่ง 'T' ช่วยให้สแต็กสามารถเก็บองค์ประกอบประเภทใดก็ได้ ประเภท 'Stack' ถูกนำมาใช้เป็นส่วนหนึ่งขององค์ประกอบประเภท 'T' ที่นี่ มีการปรับใช้สองฟังก์ชันสำหรับประเภท 'Stack': 'Push' และ 'Pop' ฟังก์ชัน Push() มีหน้าที่เพิ่มองค์ประกอบลงในสแต็ก ใช้รายการอาร์กิวเมนต์ประเภท 'T' และต่อท้ายส่วนย่อยโดยใช้ฟังก์ชันผนวก ()

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

ถัดไป กองจำนวนเต็มใหม่จะถูกสร้างขึ้นโดยใช้ไวยากรณ์ Stack[int] ภายในฟังก์ชันหลักของโค้ดนี้ หลังจากนั้นเมธอด “พุช” จะถูกเรียกใช้สามครั้งเพื่อเพิ่มจำนวนเต็ม 1, 2 และ 3 ลงในสแต็ก อย่างไรก็ตาม เมธอด 'ป๊อป' จะถูกเรียกสามครั้งในภายหลังเพื่อดึงและพิมพ์องค์ประกอบจากสแต็ก

เอาต์พุตต่อไปนี้บ่งชี้ว่าองค์ประกอบถูกลบออกจากสแต็กในลำดับย้อนกลับ:

ตัวอย่างที่ 4: การใช้ข้อจำกัดทั่วไปของ Golang

นอกจากนี้ Go ยังเสนอข้อจำกัดแบบกำหนดเองที่ช่วยให้มีความยืดหยุ่นสูงและกำหนดข้อกำหนดเฉพาะสำหรับโครงสร้างทั่วไปตามความต้องการของแอปพลิเคชัน รหัสของข้อจำกัดทั่วไปที่กำหนดเองมีให้ในการสาธิตต่อไปนี้:

บรรจุุภัณฑ์ หลัก
นำเข้า 'เอฟเอ็มที'
พิมพ์ ตัวเลข อินเตอร์เฟซ {
int64 | float64
}
ฟังก์ชั่น หลัก () {
FloatValue := [] float64 { 2 . 0 , 4 . 0 , 6 . 0 , 8 . 0 , 10 . 0 }
ค่าจำนวนเต็ม := [] int64 { 2 , 4 , 6 , 8 , 10 }
ผลรวม1 := ผลรวมทั่วไป ( FloatValue )
ผลรวม 2 := ผลรวมทั่วไป ( ค่าจำนวนเต็ม
เอฟเอ็มที . พิมพ์ ( 'ผลรวมของ float64 :' , ผลรวม1 )
เอฟเอ็มที . พิมพ์ ( 'ผลรวมของ int64 :' , ผลรวม 2 )

}
ฟังก์ชั่น ผลรวมทั่วไป [ น. ตัวเลข ]( ตัวเลข [] ) {
เคยเป็น ฉันคือ น
สำหรับ _ , ในหนึ่ง := พิสัย ตัวเลข {
ผลรวม += ในหนึ่ง
}
กลับ ผลรวม
}

ในซอร์สโค้ดก่อนหน้า เรากำหนดอินเทอร์เฟซตัวเลขด้วยวิธี 'ผลรวม' จากนั้น เราสร้างประเภทที่กำหนดเองสองประเภท ได้แก่ “FloatValue” และ “IntegerValue” ซึ่งใช้อินเทอร์เฟซตัวเลขโดยระบุวิธี “ผลรวม” ตามลำดับ ขณะนี้ ฟังก์ชัน genericSum สามารถรับส่วนแบ่งของประเภทใดก็ได้ที่ตรงกับอินเทอร์เฟซตัวเลข ภายในฟังก์ชัน เราวนซ้ำองค์ประกอบต่างๆ และเรียกใช้เมธอด 'Sum' เพื่อคำนวณผลรวม สุดท้าย ในฟังก์ชันหลัก เราสร้างส่วนของ FloatValue และ IntegerValue และส่งต่อไปยังฟังก์ชัน genericSum() ซึ่งจะคำนวณผลรวมขององค์ประกอบในแต่ละส่วนได้อย่างถูกต้อง

ผลลัพธ์ที่คาดหวังจะปรากฏบนหน้าจอต่อไปนี้:

บทสรุป

เราสำรวจตัวอย่างที่ใช้งานได้จริงของ Go generics ซึ่งรวมถึงการสร้างโครงสร้างข้อมูลทั่วไปและฟังก์ชันทั่วไป การกำหนดอินเทอร์เฟซทั่วไป และการใช้ข้อจำกัดประเภทที่กำหนดเอง ตัวอย่างเหล่านี้แสดงให้เห็นถึงพลังและความยืดหยุ่นที่โปรแกรมทั่วไปนำมาสู่ภาษาโปรแกรม Go โปรดทราบว่าการสร้างรหัสทั่วไประหว่างการคอมไพล์ทำให้มั่นใจได้ถึงขนาดไบนารีที่มีประสิทธิภาพและเวลาในการคอมไพล์