กลับไปหน้าบทความ

อ่าน 25 นาที

โก (ภาษาโปรแกรม)

Go เป็น ภาษาโปรแกรม ระดับ สูง อเนกประสงค์ ที่มี การกำหนดประเภทแบบคงที่ และ คอมไพล์...

โก (ภาษาโปรแกรม)

ไป
กระบวนทัศน์หลายกระบวนทัศน์ : พร้อมกัน , เชิงบังคับ , เชิงฟังก์ชัน , [ 1 ]เชิงวัตถุ[ 2 ] [ 3 ]
ออกแบบโดยโรเบิร์ต กรีสเมอร์ร็อบ ไพค์เคน ทอมป์สัน[ 4 ]
นักพัฒนาผู้เขียน Go [ 5 ]
ปรากฏครั้งแรก10 พฤศจิกายน 2552 ( 10 พฤศจิกายน 2009 )
เวอร์ชันเสถียร
1.26.4 [ 6 ] แก้ไขข้อมูลนี้บนวิกิดาต้า / 2 มิถุนายน 2026 ( 2 มิถุนายน 2569 )
วินัยในการพิมพ์อนุมาน , คงที่ , แข็งแกร่ง , [ 7 ]โครงสร้าง , [ 8 ] [ 9 ]นาม
การจัดการหน่วยความจำการเก็บขยะ
ภาษาการใช้งานภาษา Go, ภาษาแอสเซมบลี (gc); ภาษา C++ (gofrontend)
โอเอสDragonFly BSD , FreeBSD , Linux , macOS , NetBSD , OpenBSD , [ 10 ] Plan 9 , [ 11 ] Solaris , Windows
ใบอนุญาตBSD 3 ข้อ[ 5 ] + การให้สิทธิบัตร[ 12 ]
นามสกุลไฟล์.ไป
เว็บไซต์ไป.devแก้ไขข้อมูลนี้ได้ที่วิกิดาต้า
การนำไปใช้งานหลักๆ
จีซี, โกฟรอนต์เอนด์, โกลด์
ได้รับอิทธิพลจาก
C , Oberon-2 , Limbo , Active Oberon ,กระบวนการสื่อสารแบบลำดับ , Pascal , Oberon , Smalltalk , Newsqueak , Modula-2 , Alef , APL , BCPL , Modula , occam
ได้รับอิทธิพล
คริสตัลวี

Goเป็น ภาษาโปรแกรม ระดับสูงอเนกประสงค์ที่มีการกำหนดประเภทแบบคงที่และคอมไพล์เป็นที่รู้จักในด้านความเรียบง่ายของไวยากรณ์และประสิทธิภาพในการพัฒนาที่เกิดจากการรวมไลบรารีมาตรฐานขนาดใหญ่ที่ตอบสนองความต้องการมากมายสำหรับโครงการทั่วไป[ 13 ]ได้รับการออกแบบที่Google [ 14 ]ในปี 2007 โดยRobert Griesemer , Rob PikeและKen Thompsonและประกาศต่อสาธารณะในเดือนพฤศจิกายน 2009 [ 4 ]มีไวยากรณ์คล้ายกับCแต่ยังมีการเก็บขยะการกำหนดประเภทเชิงโครงสร้าง[ 8 ]และการทำงานพร้อมกันแบบCSP [ 15 ]มักเรียกกันว่าGolangเพื่อหลีกเลี่ยงความกำกวมและเนื่องจากชื่อโดเมนเดิมอย่างไรก็ตาม ชื่อที่ถูกต้องคือ Go [ 16 ]golang.org

มีการใช้งานหลักสองแบบ:

GopherJS ซึ่งเป็นคอมไพเลอร์จากซอร์สโค้ดของบุคคลที่สาม[ 22 ]แปลง Go เป็นJavaScriptสำหรับการพัฒนาเว็บฝั่ง front- end

ประวัติศาสตร์

Go ได้รับการออกแบบที่Googleในปี 2550 เพื่อปรับปรุงประสิทธิภาพการเขียนโปรแกรมในยุคของ เครื่อง มัลติคอร์เครื่องเครือข่าย และโค้ดเบสขนาดใหญ่[ 23 ]นักออกแบบต้องการแก้ไขข้อวิจารณ์ของภาษาอื่นๆ ที่ใช้ใน Google แต่ยังคงรักษาคุณลักษณะที่เป็นประโยชน์ไว้[ 24 ]

นักออกแบบส่วนใหญ่มีแรงจูงใจมาจากความไม่ชอบC++ ร่วม กัน[ 26 ] [ 27 ] [ 28 ]

Go ได้รับการประกาศต่อสาธารณะในเดือนพฤศจิกายน พ.ศ. 2552 [ 29 ]และเวอร์ชัน 1.0 ได้รับการเผยแพร่ในเดือนมีนาคม พ.ศ. 2555 [ 30 ] [ 31 ] Go ถูกนำไปใช้งานอย่างแพร่หลายในการผลิตที่ Google [ 32 ]และในองค์กรและโครงการโอเพนซอร์สอื่นๆ อีกมากมาย

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

แม้ว่าการออกแบบภาษาส่วนใหญ่จะมุ่งเน้นไปที่นวัตกรรมในด้านไวยากรณ์ ความหมาย หรือการกำหนดประเภท แต่ Go มุ่งเน้นไปที่กระบวนการพัฒนาซอฟต์แวร์เอง ... คุณสมบัติที่โดดเด่นของภาษาเอง—การทำงานพร้อมกัน—ได้แก้ไขปัญหาที่เกิดขึ้นจากการแพร่หลายของซีพียูแบบมัลติคอร์ในช่วงทศวรรษ 2010 แต่สิ่งที่สำคัญกว่านั้นคืองานในช่วงแรกๆ ที่ได้วางรากฐานสำหรับการบรรจุ การพึ่งพา การสร้าง การทดสอบ การปรับใช้ และงานประจำวันอื่นๆ ในโลกของการพัฒนาซอฟต์แวร์ ซึ่งเป็นแง่มุมที่โดยปกติแล้วไม่ได้ถูกให้ความสำคัญเป็นอันดับแรกในการออกแบบภาษา[ 33 ]

การสร้างแบรนด์และการออกแบบ

ภาพวาดมาสคอตของ Go ซึ่งเป็นตัวตุ่นการ์ตูน

มาสคอต ตัวตุ่น ถูกนำมาใช้ในปี 2009 สำหรับ การเปิด ตัวภาษาแบบโอเพนซอร์สRenée Frenchผู้ซึ่งออกแบบมาสคอตกระต่ายสำหรับPlan 9ได้ดัดแปลงมาสคอตตัวตุ่นจากแบบเสื้อยืดWFMU รุ่นก่อนหน้า [ 34 ]

ในเดือนพฤศจิกายน พ.ศ. 2559 แบบอักษร Go และ Go Mono ได้รับการเผยแพร่โดยนักออกแบบตัวอักษรCharles BigelowและKris Holmesโดยเฉพาะสำหรับใช้ในโครงการ Go Go เป็นแบบอักษร sans-serif แบบมนุษยนิยมที่คล้ายกับLucida Grandeและ Go Mono เป็น แบบอักษร monospacedแบบอักษรทั้งสองเป็นไปตาม ชุดอักขระ WGL4และได้รับการออกแบบให้สามารถอ่านได้ง่ายด้วยความสูงของตัวอักษร x ที่ใหญ่ และรูปทรงตัวอักษร ที่แตกต่างกัน ทั้ง Go และ Go Mono เป็นไปตาม มาตรฐาน DIN 1450 โดยมีเลขศูนย์ขีดทับ ตัวพิมพ์เล็กiมีหาง และตัวพิมพ์ใหญ่Iมี serif [ 35 ] [ 36 ]

ในเดือนเมษายน พ.ศ. 2561 โลโก้เดิมได้รับการออกแบบใหม่โดย Adam Smith นักออกแบบแบรนด์ โลโก้ใหม่เป็นตัวอักษร GO ที่ทันสมัยและมีสไตล์เอียงไปทางขวาพร้อมเส้นสายที่ลากยาว มาสคอตตัวโกเฟอร์ยังคงเหมือนเดิม[ 37 ]

ยาสามัญ

การขาดการสนับสนุนการเขียนโปรแกรมแบบเจเนริกในเวอร์ชันเริ่มต้นของ Go ได้รับการวิพากษ์วิจารณ์อย่างมาก[ 38 ]นักออกแบบแสดงความเปิดกว้างต่อการเขียนโปรแกรมแบบเจเนริกและสังเกตว่าฟังก์ชันในตัวนั้นเป็นแบบเจเนริกตามประเภท แต่ได้รับการปฏิบัติเหมือนเป็นกรณีพิเศษ ไพค์เรียกสิ่งนี้ว่าเป็นจุดอ่อนที่อาจมีการเปลี่ยนแปลงในบางจุด[ 39 ]ทีม Google สร้างคอมไพเลอร์อย่างน้อยหนึ่งตัวสำหรับภาษา Go ทดลองที่มีเจเนริก แต่ไม่ได้เผยแพร่[ 40 ]

ในเดือนสิงหาคม พ.ศ. 2561 ผู้มีส่วนร่วมหลักของ Go ได้เผยแพร่ร่างการออกแบบสำหรับการเขียนโปรแกรมทั่วไปและการจัดการข้อผิดพลาดและขอให้ผู้ใช้ส่งข้อเสนอแนะ[ 41 ] [ 42 ]อย่างไรก็ตาม ข้อเสนอการจัดการข้อผิดพลาดถูกยกเลิกในที่สุด[ 43 ]

ในเดือนมิถุนายน พ.ศ. 2563 มีการเผยแพร่ร่างเอกสารการออกแบบฉบับใหม่[ 44 ]ซึ่งจะเพิ่มไวยากรณ์ที่จำเป็นให้กับ Go สำหรับการประกาศฟังก์ชันและประเภททั่วไป เครื่องมือแปลโค้ดgo2goได้รับการจัดเตรียมไว้เพื่อให้ผู้ใช้สามารถลองใช้ไวยากรณ์ใหม่ พร้อมกับ Go Playground เวอร์ชันออนไลน์ที่เปิดใช้งานเจเนริก[ 45 ]

Generics ถูกเพิ่มเข้าไปใน Go เวอร์ชัน 1.18 ในวันที่ 15 มีนาคม 2022 [ 46 ]

การกำหนดเวอร์ชัน

Go 1 รับประกันความเข้ากันได้[ 47 ]สำหรับข้อกำหนดภาษาและส่วนสำคัญของไลบรารีมาตรฐาน ทุกเวอร์ชันจนถึง Go 1.26 เวอร์ชันปัจจุบัน[ 48 ]ยังคงรักษาสัญญานี้ไว้

Go ใช้go1.[major].[patch]รูปแบบการกำหนดเวอร์ชัน เช่นgo1.26.0และแต่ละเวอร์ชันหลักของ Go จะได้รับการสนับสนุนจนกว่าจะมีเวอร์ชันหลักที่ใหม่กว่าสองเวอร์ชัน ไม่เหมือนกับซอฟต์แวร์ส่วนใหญ่ Go เรียกตัวเลขที่สองในเวอร์ชันว่าเวอร์ชันหลัก เช่น ในgo1.26.0คือ26เวอร์ชันหลัก[ 49 ]ทั้งนี้เพราะ Go วางแผนที่จะไม่ถึงเวอร์ชัน 2.0 โดยให้ความสำคัญกับความเข้ากันได้กับเวอร์ชันก่อนหน้ามากกว่าการเปลี่ยนแปลงที่อาจทำให้เกิดปัญหา[ 50 ]

ออกแบบ

การบรรยายของ ร็อบ ไพค์ (หนึ่งในผู้สร้างเกมโกะ) ในปี 2015

Go ได้รับอิทธิพลจากC (โดยเฉพาะภาษาถิ่นPlan 9 [ 51 ] ) แต่เน้นความเรียบง่ายและความปลอดภัยมากขึ้น ประกอบด้วย:

ไวยากรณ์

ไวยากรณ์ของ Go มีการเปลี่ยนแปลงจากภาษา Cโดยมีเป้าหมายเพื่อให้โค้ดกระชับและอ่านง่าย มีการนำตัวดำเนินการประกาศ/กำหนดค่าเริ่มต้นแบบรวมมาใช้ ซึ่งช่วยให้นักเขียนโปรแกรมสามารถเขียน `new` หรือ`new` ได้โดยไม่ต้องระบุชนิดของตัวแปรที่ใช้ ซึ่งแตกต่างจาก `new` และ `new` ในภาษา C (แม้ว่าตั้งแต่C23 เป็นต้นมา จะรองรับการอนุมานชนิดข้อมูลโดยใช้ `new` เช่นเดียวกับในC++ ก็ตาม ) นอกจากนี้ Go ยังยกเลิกข้อกำหนดในการใช้วงเล็บในเงื่อนไขของคำสั่ง อีกด้วยi:=3s:="Hello, world!"inti=3;char*s="Hello, world!";autoif

เครื่องหมายเซมิโคลอนยังคงใช้ปิดท้ายประโยค[]แต่จะถือว่าไม่มีเครื่องหมายเซมิโคลอนเมื่อสิ้นสุดบรรทัด[]

เมธอดอาจส่งคืนค่าได้หลายค่า และการส่งคืนคู่ค่าถือเป็นวิธีปกติที่เมธอดจะระบุข้อผิดพลาดให้กับผู้เรียกใน Go [ c ] Go เพิ่มไวยากรณ์ตัวอักษรสำหรับการเริ่มต้นพารามิเตอร์โครงสร้างตามชื่อ และสำหรับการเริ่มต้นแผนที่และสไลซ์ ในฐานะทางเลือกแทน ลูปสามคำสั่งของ C นิพจน์ของ Go ช่วยให้สามารถวนซ้ำอย่างกระชับเหนืออาร์เรย์ สไลซ์ สตริง แผนที่ และช่องสัญญาณ[ 59 ]result,errforrange

คำสำคัญ

Go ประกอบด้วยคีย์เวิร์ดต่อไปนี้ 25 คำ: [ 60 ]

  • break
  • case
  • chan
  • const
  • continue
  • default
  • defer
  • else
  • fallthrough
  • for
  • func
  • go
  • goto
  • if
  • import
  • interface
  • map
  • package
  • range
  • return
  • select
  • struct
  • switch
  • type
  • var

ประเภท

Go มีประเภทข้อมูลในตัวหลายประเภท รวมถึงประเภทตัวเลข ( byte, int64, float32, เป็นต้น) ประเภทบูลีนและประเภทสตริงไบต์ ( string) สตริงไม่สามารถเปลี่ยนแปลงได้ ตัวดำเนินการและคำหลักในตัว (แทนที่จะเป็นฟังก์ชัน) จะให้การเชื่อมต่อ การเปรียบเทียบ และการเข้ารหัส/ถอดรหัสUTF-8 [ 61 ]ประเภทเรคอร์ดสามารถกำหนดได้ด้วยstructคำหลัก[ 62 ]

Go ประกอบด้วยองค์ประกอบพื้นฐานต่อไปนี้: [ 63 ]

  • bool
  • int8
  • uint8
  • int16
  • uint16
  • int32
  • uint32
  • int64
  • uint64
  • int
  • uint
  • uintptr
  • float32
  • float64
  • complex64
  • complex128
  • string

โปรดทราบว่าbyteเป็นชื่อเรียกแทนของuint8และruneเป็นชื่อเรียกแทนint32ของ

สำหรับแต่ละประเภทTและค่าคงที่จำนวนเต็มที่ไม่เป็นลบแต่ละค่าnจะมีประเภทอาร์เรย์ที่กำหนดไว้[n]Tอาร์เรย์ที่มีความยาวต่างกันจึงมีประเภทต่างกันอาร์เรย์แบบไดนามิกมีให้ใช้งานในรูปแบบ "สไลซ์" ซึ่งกำหนดไว้[]TสำหรับประเภทบางประเภทT(เปรียบเทียบกับภาษาอื่นๆ เช่น C/C++ และJavaซึ่งอาร์เรย์จะถูกกำหนดไว้แทนT[]) สไลซ์เหล่านี้มีความยาวและความจุที่ระบุว่าเมื่อใดจำเป็นต้องจัดสรรหน่วยความจำใหม่เพื่อขยายอาร์เรย์ สไลซ์หลายสไลซ์อาจใช้หน่วยความจำพื้นฐานร่วมกัน[ 39 ] [ 64 ] [ 65 ]

ตัวชี้มีให้สำหรับทุกประเภท และตัวชี้ไปยังTประเภทจะถูกระบุ*T(คล้ายกับ Rust ; เปรียบเทียบกับภาษาอื่นๆ เช่น C/C++ และ C#ซึ่งตัวชี้จะถูกระบุT*) การรับที่อยู่และการอ้างอิงทางอ้อมใช้&and*เช่นเดียวกับใน C หรือเกิดขึ้นโดยปริยายผ่านการเรียกเมธอดหรือไวยากรณ์การเข้าถึงแอตทริบิวต์ [ 66 ] [ 67 ]ไม่มีการคำนวณเลขคณิตของตัวชี้ [ d ]ยกเว้นผ่านประเภทพิเศษunsafe.Pointerในไลบรารีมาตรฐาน [ 68 ]

สำหรับคู่ของประเภทK, V, ประเภทmap[K]Vคือประเภทที่แมปคีย์ประเภทKกับVค่าประเภท ซึ่งสามารถคิดได้ว่าเทียบเท่ากับMap<K, V>ในภาษาอื่นๆ ข้อกำหนดของภาษาการเขียนโปรแกรม Go ไม่ได้ให้การรับประกันประสิทธิภาพหรือข้อกำหนดการใช้งานใดๆ สำหรับประเภทแผนที่ แม้ว่าโดยทั่วไปจะถูกนำไปใช้เป็นตารางแฮช (เทียบเท่ากับHashMap<K, V>ในภาษาอื่นๆ) ตารางแฮชถูกสร้างขึ้นในภาษาด้วยไวยากรณ์พิเศษและฟังก์ชันในตัวchan Tเป็นช่องทางที่อนุญาตให้ส่งค่าประเภทTระหว่างกระบวนการ Go ที่ทำงานพร้อมกัน[ 69 ]

นอกเหนือจากการสนับสนุนอินเทอร์เฟซแล้วระบบประเภทของ Go เป็นแบบนามนัย : typeคำหลักสามารถใช้เพื่อกำหนดประเภทที่มีชื่อ ใหม่ ซึ่งแตกต่างจากประเภทที่มีชื่ออื่นๆ ที่มีโครงสร้างเดียวกัน (ในกรณีของ คือstructสมาชิกเดียวกันในลำดับเดียวกัน) การแปลงระหว่างประเภทบางอย่าง (เช่น ระหว่างประเภทจำนวนเต็มต่างๆ) ถูกกำหนดไว้ล่วงหน้า และการเพิ่มประเภทใหม่อาจกำหนดการแปลงเพิ่มเติม แต่การแปลงระหว่างประเภทที่มีชื่อจะต้องเรียกใช้อย่างชัดเจนเสมอ[ 70 ]ตัวอย่างเช่นtypeคำหลักสามารถใช้เพื่อกำหนดประเภทสำหรับ ที่อยู่ IPv4โดยอิงจากจำนวนเต็มที่ไม่มีเครื่องหมาย 32 บิต ดังนี้:

ประเภทipv4addr uint32

ด้วยคำจำกัดความประเภทนี้ipv4addr(x)จะตีความuint32ค่าxเป็นที่อยู่ IP การกำหนดค่าxให้กับตัวแปรประเภทนั้นipv4addrถือเป็นข้อผิดพลาดประเภท[ 71 ]

นิพจน์คงที่อาจเป็นแบบมีประเภทหรือ "ไม่มีประเภท" โดยจะได้รับประเภทเมื่อกำหนดให้กับตัวแปรที่มีประเภท หากค่าที่แสดงผ่านการตรวจสอบในเวลาคอมไพล์[ 72 ]

ประเภทของฟังก์ชันระบุโดยfuncคำหลัก โดยรับพารามิเตอร์ ตั้งแต่ศูนย์ตัวขึ้นไป และส่งคืนค่าตั้งแต่ศูนย์ตัวขึ้นไป ซึ่งทั้งหมดเป็นประเภทที่กำหนด พารามิเตอร์และค่าที่ส่งคืนจะกำหนดประเภทของฟังก์ชัน ดังนั้น จึงfunc(string, int32) (int, error)เป็นประเภทของฟังก์ชันที่รับ astringและจำนวนเต็มที่มีเครื่องหมาย 32 บิต และส่งคืนค่าจำนวนเต็มที่มีเครื่องหมาย (ความกว้างเริ่มต้น) และค่าของประเภทอินเทอร์เฟซในerrorตัว [ 73 ]

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

// ZeroBroadcast รายงานว่า addr คือ 255.255.255.255 หรือไม่func ( addr ipv4addr ) ZeroBroadcast () bool { return addr == 0xFFFFFFFF }

เนื่องจากการกำหนดประเภทตามนาม การกำหนดวิธีการนี้จะเพิ่มวิธีการลงในipv4addrแต่ไม่ใช่บนuint32ในขณะที่วิธีการมีการกำหนดและไวยากรณ์การเรียกใช้พิเศษ แต่ไม่มีประเภทวิธีการที่แตกต่างกัน[ 74 ]

ระบบอินเทอร์เฟซ

Go มีคุณสมบัติสองอย่างที่ใช้แทนการ สืบทอดคลาส

ประการแรกคือการฝังซึ่งสามารถมองได้ว่าเป็นรูปแบบการจัดองค์ประกอบแบบ อัตโนมัติ [ 75 ]

ประการที่สองคืออินเทอร์เฟซซึ่งให้โพลีมอร์ฟิซึมขณะรันไทม์ [ 76 ] : 266 อินเทอร์เฟซเป็นคลาสของประเภทและให้รูปแบบการกำหนดประเภทเชิงโครงสร้าง ที่จำกัด ในระบบประเภทนามของ Go วัตถุที่เป็นประเภทอินเทอร์เฟซก็เป็นประเภทอื่นด้วยเช่นกัน คล้ายกับ วัตถุ C++ที่เป็นทั้งคลาสพื้นฐานและคลาสที่สืบทอดมาพร้อมกัน การออกแบบอินเทอร์เฟซของ Go ได้รับแรงบันดาลใจจากโปรโตคอลจากภาษาโปรแกรม Smalltalk [ 77 ]แหล่งข้อมูลหลายแห่งใช้คำว่าduck typingเมื่ออธิบายอินเทอร์เฟซของ Go [ 78 ] [ 79 ]แม้ว่าคำว่า duck typing จะไม่ได้กำหนดไว้อย่างแม่นยำและจึงไม่ผิด แต่โดยทั่วไปแล้วหมายความว่าไม่ได้ตรวจสอบความสอดคล้องของประเภทแบบคงที่ เนื่องจากความสอดคล้องกับอินเทอร์เฟซของ Go จะถูกตรวจสอบแบบคงที่โดยคอมไพเลอร์ของ Go (ยกเว้นเมื่อทำการยืนยันประเภท) ผู้เขียน Go จึงชอบใช้คำว่าstructural typingมากกว่า[ 80 ]

นิยามของประเภทอินเทอร์เฟซจะแสดงรายการเมธอดที่จำเป็นโดยระบุชื่อและประเภท วัตถุใดๆ ของประเภท T ที่มีฟังก์ชันตรงกับเมธอดที่จำเป็นทั้งหมดของประเภทอินเทอร์เฟซ I ก็จะเป็นวัตถุของประเภท I เช่นกัน นิยามของประเภท T ไม่จำเป็นต้อง (และไม่สามารถ) ระบุประเภท I ตัวอย่างเช่น ถ้าShapeและSquareand Circleถูกกำหนดเป็น

นำเข้า"คณิตศาสตร์"อิน เทอร์เฟซประเภทShape { พื้นที่() float64 }// หมายเหตุ: ไม่มีการประกาศ "implements" type Square struct { side float64 }func ( sq Square ) Area () float64 { return sq . side * sq . side }// ไม่มีการประกาศ "implements" ที่นี่เช่นกันtype Circle struct { radius float64 }func ( c Circle ) Area () float64 { return math . Pi * math . Pow ( c . radius , 2 ) }

จากนั้นทั้ง a Squareและ a Circleต่างก็เป็น a โดยปริยายShapeและสามารถกำหนดให้กับShapeตัวแปรประเภท a ได้[ 76 ] : 263–268 ในภาษาทางการ ระบบอินเทอร์เฟซของ Go ให้ การกำหนด ประเภทเชิงโครงสร้างมากกว่า การกำหนดประเภทเชิง นามอินเทอร์เฟซสามารถฝังอินเทอร์เฟซอื่น ๆ ได้ โดยมีผลเป็นการสร้างอินเทอร์เฟซแบบผสมที่ตรงตามประเภทที่ใช้อินเทอร์เฟซที่ฝังอยู่และเมธอดใด ๆ ที่อินเทอร์เฟซที่กำหนดใหม่เพิ่มเข้ามา[ 76 ] : 270

ไลบรารีมาตรฐานของ Go ใช้อินเทอร์เฟซเพื่อให้ความเป็นทั่วไปในหลาย ๆ ที่ รวมถึงระบบอินพุต/เอาต์พุตที่อิงตามแนวคิดของและReader[ 76 ] : 282–283 Writer

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

var shp Shape = Square { 5 } square , ok := shp .( Square ) // ยืนยันประเภท Square บน shp ซึ่งน่าจะใช้งานได้ถ้าok { fmt . Printf ( "%#v\n" , square ) } else { fmt . Println ( "ไม่สามารถพิมพ์รูปร่างเป็น Square ได้" ) }

และสวิตช์ประเภท[ 82 ]ซึ่งตรวจสอบกับหลายประเภท:

func ( sq สี่เหลี่ยม) Diagonal ( ) float64 { return sq.side * math.Sqrt2 } func ( c วงกลม) Diameter ( ) float64 { return 2 * c.radius }func LongestContainedLine ( shp Shape ) float64 { switch v := shp .( type ) { case Square : return v . Diagonal () // หรือ หากตรวจสอบประเภทแล้ว shp.(Square).Diagonal() case Circle : return v . Diameter () // หรือ หากตรวจสอบประเภทแล้ว shp.(Circle).Diameter() default : return 0 // ในทางปฏิบัติ ควรจัดการกรณีนี้ด้วยข้อผิดพลาด} }

อินเทอร์เฟซว่างเปล่า เป็นกรณีพื้นฐานที่สำคัญ เนื่องจากสามารถอ้างอิงถึงรายการของ ประเภทที่เป็นรูปธรรม ใดๆ ก็ได้คล้ายกับคลาสในJavaหรือC#หรือในCหรือในC++และRustและสามารถใช้งานได้กับทุกประเภท รวมถึงประเภทในตัว เช่น[ 76 ] : 284 โค้ดที่ใช้อินเทอร์เฟซว่างเปล่าไม่สามารถเรียกเมธอด (หรือตัวดำเนินการในตัว) บนวัตถุที่อ้างถึงได้โดยตรง แต่สามารถจัดเก็บค่า พยายามแปลงเป็นประเภทที่มีประโยชน์มากขึ้นผ่านการยืนยันประเภทหรือสวิตช์ประเภท หรือตรวจสอบด้วยแพ็กเกจ ของ Go [ 83 ]เนื่องจากสามารถอ้างอิงถึงค่าใดๆ ก็ได้ จึงเป็นวิธีที่จำกัดในการหลีกเลี่ยงข้อจำกัดของการกำหนดประเภทแบบคงที่ เช่นใน C แต่มีการตรวจสอบประเภทขณะรันไทม์เพิ่มเติม interface{}Objectvoid*Anyintinterface{}reflectinterface{}void*

ประเภท นี้สามารถใช้สร้างแบบจำลองข้อมูลที่มีโครงสร้างของสคีมาใดๆ ก็ได้ใน Go เช่น ข้อมูล JSONหรือYAMLโดยแสดงเป็น(แผนที่ของสตริงไปยังอินเทอร์เฟซว่าง) ซึ่งจะอธิบายข้อมูลแบบเรียกซ้ำในรูปแบบของพจนานุกรมที่มีคีย์เป็นสตริงและค่าเป็นประเภทใดก็ได้[ 84 ]interface{}map[string]interface{}

ค่าอินเทอร์เฟซถูกนำไปใช้โดยใช้ตัวชี้ไปยังข้อมูลและตัวชี้ตัวที่สองไปยังข้อมูลประเภทรันไทม์[ 85 ]เช่นเดียวกับประเภทอื่นๆ ที่ใช้ตัวชี้ใน Go ค่าอินเทอร์เฟซจะnilไม่ได้ถูกกำหนดค่าเริ่มต้น[ 86 ]

โค้ดทั่วไปที่ใช้ประเภทพารามิเตอร์

ตั้งแต่เวอร์ชัน 1.18 Go รองรับโค้ดทั่วไปโดยใช้ประเภทพารามิเตอร์[ 87 ]

ฟังก์ชันและประเภทในปัจจุบันสามารถเป็นแบบเจเนริกได้โดยใช้พารามิเตอร์ประเภท พารามิเตอร์ประเภทเหล่านี้ระบุไว้ภายในวงเล็บเหลี่ยม ต่อจากชื่อฟังก์ชันหรือประเภท[ 88 ]คอมไพเลอร์จะแปลงฟังก์ชันหรือประเภทเจเนริกให้เป็นแบบไม่เจเนริกโดยการแทนที่อาร์กิวเมนต์ประเภทด้วยพารามิเตอร์ประเภทที่ให้มา ไม่ว่าจะโดยผู้ใช้โดยตรงหรือการอนุมานประเภทโดยคอมไพเลอร์[ 89 ]กระบวนการแปลงนี้เรียกว่าการสร้างอินสแตนซ์ของประเภท[ 90 ]

ขณะนี้อินเทอร์เฟซสามารถกำหนดชุดของประเภท (เรียกว่าชุดประเภท) โดยใช้|ตัวดำเนินการ (Union) รวมถึงชุดของเมธอด การเปลี่ยนแปลงเหล่านี้เกิดขึ้นเพื่อรองรับข้อจำกัดของประเภทในโค้ดเจเนริก สำหรับฟังก์ชันหรือประเภทเจเนริก ข้อจำกัดสามารถคิดได้ว่าเป็นประเภทของอาร์กิวเมนต์ประเภท: เมตาประเภท~Tไวยากรณ์ใหม่นี้จะเป็นการใช้ครั้งแรกของ~เป็นโทเค็นใน Go ~Tหมายถึงชุดของประเภททั้งหมดที่มีประเภทพื้นฐานTเป็น[ 91 ]

ประเภทอินเทอร์เฟซNumber { ~ int | ~ float64 | ~ float32 | ~ int32 | ~ int64 }func Add [ T Number ]( nums ... T ) T { var sum T for _ , v := range nums { sum += v } return sum }func main () { add := Add [ int ] // การสร้างอินสแตนซ์ของประเภทprintln ( add ( 1 , 2 , 3 , 4 , 5 )) // 15res := Add ( 1.1 , 2.2 , 3.3 , 4.4 , 5.5 ) // การอนุมานประเภทprintln ( res ) // +1.650000e+001 }

ประเภทแจงนับ

Go ใช้iotaตัวระบุเพื่อสร้างค่าคงที่แบบแจงนับ[ 92 ] [ 93 ]

ประเภทไบต์ขนาดจำนวนเต็มconst ( _ = iota // ละเว้นค่าแรกโดยกำหนดให้กับตัวระบุว่างเปล่า; 0 KB ByteSize = 1 << ( 10 * iota ) // 1 << (10 * 1) == 1 << 10 == 1024; ในรูปแบบไบนารี 10000000000 MB // 1 << (10 * 2) == 1048576; ในรูปแบบไบนารี 1000000000000000000000 GB // 1 << (10 * 3) == 1073741824; ในรูปแบบไบนารี 1000000000000000000000000000000 )

ระบบบรรจุภัณฑ์

ในระบบแพ็กเกจของ Go แต่ละแพ็กเกจจะมีพาธ (เช่น"compress/bzip2"หรือ"golang.org/x/net/html") และชื่อ (เช่นbzip2หรือhtml) โดยค่าเริ่มต้น คำจำกัดความของแพ็กเกจอื่นจะต้อง มีคำนำหน้าด้วยชื่อของแพ็กเกจอื่น เสมออย่างไรก็ตาม ชื่อที่ใช้สามารถเปลี่ยนแปลงได้จากชื่อแพ็กเกจ และหากนำเข้าเป็น_ก็ไม่จำเป็นต้องมีคำนำหน้าแพ็กเกจ เฉพาะ ชื่อ ที่เป็นตัวพิมพ์ใหญ่จากแพ็กเกจอื่นเท่านั้นที่สามารถเข้าถึงได้: io.Readerเป็นสาธารณะ แต่bzip2.readerไม่ใช่[ 94 ]คำgo getสั่ง สามารถดึงแพ็กเกจที่จัดเก็บไว้ในที่เก็บระยะไกลได้[ 95 ]และนักพัฒนาควรพัฒนาแพ็กเกจภายในพาธฐานที่สอดคล้องกับที่เก็บซอร์สโค้ด (เช่น example.com/user_name/package_name) เพื่อลดโอกาสการชนกันของชื่อกับส่วนเพิ่มเติมในอนาคตของไลบรารีมาตรฐานหรือไลบรารีภายนอกอื่นๆ[ 96 ]

การทำงานพร้อมกัน: โกรูทีนและแชนเนล

DotGo 2015 - Matt Aimonetti - การประยุกต์ใช้การทำงานพร้อมกันในภาษา Go

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

โครงสร้างการทำงานพร้อมกันหลักคือgoroutine ซึ่งเป็น เธรดสีเขียวประเภทหนึ่ง[ 98 ] : 280–281 การเรียกฟังก์ชันที่ขึ้นต้นด้วยgoคีย์เวิร์ดจะเริ่มต้นฟังก์ชันใน goroutine ใหม่ ข้อกำหนดของภาษาไม่ได้ระบุวิธีการใช้งาน goroutine แต่การใช้งานในปัจจุบันจะมัลติเพล็กซ์ goroutine ของกระบวนการ Go ไปยังชุดเธรดระบบปฏิบัติการ ขนาดเล็กกว่า คล้ายกับการจัดกำหนดการที่ดำเนินการในErlangและ การใช้งานรันไทม์ Glasgow Haskell Compiler (GHC) ของHaskell [ 99 ] : 10

แม้ว่า จะมีแพ็กเกจไลบรารีมาตรฐานที่มี โครงสร้าง ควบคุมการทำงานพร้อมกัน แบบคลาสสิกส่วนใหญ่ ( เช่น ล็อก มิวเท็กซ์ เป็นต้น) [ 99 ] : 151–152 แต่โปรแกรมที่ทำงานพร้อมกันตามแบบฉบับดั้งเดิมกลับนิยมใช้ช่องทาง (channels ) ซึ่งส่งข้อความระหว่างโกรูทีน[ 100 ]บัฟเฟอร์เสริมจะจัดเก็บข้อความตามลำดับFIFO [ 101 ] : 43 และอนุญาตให้โกรูทีนที่กำลังส่งดำเนินการต่อไปก่อนที่จะได้รับข้อความ[ 98 ] : 233

ช่องสัญญาณมีการกำหนดประเภทไว้ ดังนั้นช่องสัญญาณประเภทหนึ่งจึงchan Tสามารถใช้ในการถ่ายโอนข้อความประเภทหนึ่งเท่านั้นTมีการใช้ไวยากรณ์พิเศษในการดำเนินการกับช่องสัญญาณเหล่านั้น<-chโดยเป็นนิพจน์ที่ทำให้ goroutine ที่กำลังทำงานอยู่หยุดรอจนกว่าจะมีค่าเข้ามาทางช่องสัญญาณchในขณะที่ch <- xจะส่งค่าx(อาจหยุดรอจนกว่า goroutine อื่นจะได้รับค่า) คำสั่งแบบในตัวที่switchคล้ายกับselectคำสั่ง สามารถใช้เพื่อใช้งานการสื่อสารแบบไม่บล็อกบนหลายช่องสัญญาณ ดู ตัวอย่าง ด้านล่าง Go มีแบบจำลองหน่วยความจำที่อธิบายว่า goroutine ต้องใช้ช่องสัญญาณหรือการดำเนินการอื่นๆ อย่างไรเพื่อแบ่งปันข้อมูลอย่างปลอดภัย[ 102 ]

การมีอยู่ของช่องสัญญาณไม่ได้ทำให้ Go แตกต่างจาก ภาษาแบบขนานสไตล์ Actor Modelเช่น Erlang ซึ่งข้อความจะถูกส่งตรงไปยัง Actor (ซึ่งสอดคล้องกับ Goroutine) ใน Actor Model ช่องสัญญาณเองก็เป็น Actor ดังนั้นการกล่าวถึงช่องสัญญาณจึงหมายถึงการกล่าวถึง Actor รูปแบบ Actor สามารถจำลองได้ใน Go โดยการรักษาความสัมพันธ์แบบหนึ่งต่อหนึ่งระหว่าง Goroutine และช่องสัญญาณ แต่ภาษานี้อนุญาตให้ Goroutine หลายตัวใช้ช่องสัญญาณร่วมกัน หรือ Goroutine ตัวเดียวสามารถส่งและรับข้อมูลบนหลายช่องสัญญาณได้[ 99 ] : 147

จากเครื่องมือเหล่านี้ เราสามารถสร้างโครงสร้างแบบขนานได้ เช่นกลุ่มผู้ปฏิบัติงานท่อส่งข้อมูล (ซึ่งไฟล์จะถูกบีบอัดและแยกวิเคราะห์ขณะดาวน์โหลด) การเรียกใช้พื้นหลังที่มีการหมดเวลา การเรียกใช้แบบขนาน "กระจาย" ไปยังชุดบริการ และอื่นๆ[ 103 ]ช่องสัญญาณยังถูกนำไปใช้ในลักษณะที่แตกต่างจากแนวคิดปกติของการสื่อสารระหว่างกระบวนการ เช่น การทำหน้าที่เป็นรายการบัฟเฟอร์ที่รีไซเคิลได้อย่างปลอดภัยสำหรับการทำงานแบบขนาน[ 104 ]การใช้งานโครูทีน (ซึ่งเป็นแรงบันดาลใจให้เกิดชื่อโกรูทีน ) [ 105 ]และการใช้งานตัววนซ้ำ[ 106 ]

ข้อกำหนดเชิงโครงสร้างที่เกี่ยวข้องกับการทำงานพร้อมกันของ Go ( ช่องสัญญาณและอินพุตช่องสัญญาณทางเลือก) มาจาก แบบจำลอง กระบวนการลำดับการสื่อสารของ Tony Hoare แตกต่างจากภาษาการเขียนโปรแกรมพร้อมกันก่อนหน้านี้ เช่นOccamหรือLimbo (ภาษาที่ Rob Pike ผู้ร่วมออกแบบ Go ทำงานด้วย) [ 107 ] Go ไม่ได้ให้แนวคิดเรื่องการทำงานพร้อมกันที่ปลอดภัยหรือตรวจสอบได้ในตัว[ 108 ]แม้ว่าแบบจำลองกระบวนการสื่อสารจะเป็นที่นิยมใน Go แต่มันก็ไม่ใช่แบบจำลองเดียว: โกรูทีนทั้งหมดในโปรแกรมใช้พื้นที่แอดเดรสร่วมกัน ซึ่งหมายความว่าวัตถุที่เปลี่ยนแปลงได้และพอยเตอร์สามารถใช้ร่วมกันระหว่างโกรูทีนได้ ดู§ การขาดความปลอดภัยจากการแข่งขันข้อมูลด้านล่าง

ความเหมาะสมสำหรับการเขียนโปรแกรมแบบขนาน

แม้ว่าคุณสมบัติการทำงานพร้อมกันของ Go จะไม่ได้มุ่งเน้นไปที่การประมวลผลแบบขนานเป็น หลัก [ 97 ] แต่ ก็สามารถใช้ในการเขียนโปรแกรม เครื่อง มัลติโปรเซสเซอร์แบบหน่วยความจำร่วมได้ มีการศึกษาวิจัยต่างๆ เกี่ยวกับประสิทธิภาพของแนวทางนี้[ 109 ]หนึ่งในงานวิจัยเหล่านี้ได้เปรียบเทียบขนาด (ในบรรทัดของโค้ด ) และความเร็วของโปรแกรมที่เขียนโดยโปรแกรมเมอร์ที่มีประสบการณ์ซึ่งไม่คุ้นเคยกับภาษา และการแก้ไขโปรแกรมเหล่านี้โดยผู้เชี่ยวชาญด้าน Go (จากทีมพัฒนาของ Google) โดยทำเช่นเดียวกันกับChapel , CilkและIntel TBBงานวิจัยพบว่าผู้ที่ไม่เชี่ยวชาญมักจะเขียน อัลกอริทึม แบบแบ่งและพิชิตโดยใช้คำสั่งเดียวต่อการเรียกซ้ำ ในขณะที่ผู้เชี่ยวชาญเขียนโปรแกรมแบบกระจายงานและซิงโครไนซ์โดยใช้ goroutine หนึ่งตัวต่อแกนประมวลผล โปรแกรมของผู้เชี่ยวชาญมักจะเร็วกว่า แต่ก็ยาวกว่าด้วย[ 110 ]go

ขาดข้อมูลด้านความปลอดภัยในการแข่งขัน

แนวทางของ Go ในการจัดการการทำงานพร้อมกันสามารถสรุปได้ว่า "อย่าสื่อสารโดยการแชร์หน่วยความจำ แต่ให้แชร์หน่วยความจำโดยการสื่อสาร" [ 111 ]ไม่มีข้อจำกัดใดๆ เกี่ยวกับวิธีที่ goroutine เข้าถึงข้อมูลที่ใช้ร่วมกัน ทำให้ เกิด การแข่งขันของข้อมูลได้ โดยเฉพาะอย่างยิ่ง เว้นแต่โปรแกรมจะซิงโครไนซ์อย่างชัดเจนผ่านช่องทางหรือวิธีการอื่นๆ การเขียนจาก goroutine หนึ่งอาจมองเห็นได้บางส่วน ทั้งหมด หรือมองไม่เห็นเลยสำหรับอีก goroutine หนึ่ง โดยมักไม่มีการรับประกันเกี่ยวกับลำดับการเขียน[ 108 ] นอกจากนี้ โครงสร้างข้อมูลภายในของ Go เช่น ค่าอินเทอร์เฟซ ส่วนหัวของ slice ตารางแฮช และส่วนหัวของสตริง ก็ไม่ปลอดภัยจากการแข่งขันของข้อมูล ดังนั้นความปลอดภัยของประเภทและหน่วยความจำอาจถูกละเมิดในโปรแกรมมัลติเธรดที่แก้ไขอินสแตนซ์ที่ใช้ร่วมกันของประเภทเหล่านั้นโดยไม่ซิงโครไนซ์[ 112 ] [ 113 ]แทนที่จะอาศัยการสนับสนุนจากภาษา การเขียนโปรแกรมพร้อมกันที่ปลอดภัยจึงอาศัยข้อตกลง ตัวอย่างเช่น Chisnall แนะนำสำนวนที่เรียกว่า "aliases xor mutable" ซึ่งหมายความว่าการส่งค่าที่เปลี่ยนแปลงได้ (หรือตัวชี้) ผ่านช่องทางส่งสัญญาณการถ่ายโอนความเป็นเจ้าของค่าไปยังผู้รับ[ 99 ] : 155 ชุดเครื่องมือ gc มีตัวตรวจจับการแข่งขันข้อมูลเสริมที่สามารถตรวจสอบการเข้าถึงหน่วยความจำที่ใช้ร่วมกันที่ไม่ซิงโครไนซ์ระหว่างรันไทม์ตั้งแต่เวอร์ชัน 1.1 [ 114 ]นอกจากนี้ ตัวตรวจจับการแข่งขันแบบ best-effort ยังรวมอยู่ด้วยโดยค่าเริ่มต้นตั้งแต่เวอร์ชัน 1.6 ของรันไทม์ gc สำหรับการเข้าถึงmapประเภทข้อมูล[ 115 ]

ไบนารี

โดยค่าเริ่มต้น ตัวเชื่อมโยงในชุดเครื่องมือ gc จะสร้างไบนารีที่เชื่อมโยงแบบคงที่ ดังนั้นไบนารี Go ทั้งหมดจึงรวมรันไทม์ Go ไว้ด้วย[ 116 ] [ 117 ]

การละเว้น

Go จงใจละเว้นคุณสมบัติบางอย่างที่พบได้ทั่วไปในภาษาอื่นๆ รวมถึงการสืบทอด (การใช้งาน)การยืนยัน[ e ]การคำนวณเลขชี้ [ d ] การแปลงประเภทโดยปริยายยูเนียนที่ไม่มีแท็ก [ f ] และยูเนียนที่มีแท็ก [ g ] นักออกแบบได้เพิ่มเฉพาะสิ่งอำนวยความสะดวกที่ทั้งสามฝ่ายเห็นพ้องต้องกัน[ 120 ]

ในบรรดาคุณลักษณะของภาษาที่ถูกละเว้น นักออกแบบได้โต้แย้งอย่างชัดเจนเกี่ยวกับการยืนยันและการคำนวณตัวชี้ ในขณะที่ปกป้องการเลือกที่จะละเว้นการสืบทอดประเภทว่าจะทำให้ภาษามีประโยชน์มากขึ้น โดยสนับสนุนให้ใช้อินเทอร์เฟซแทนเพื่อบรรลุการเรียกใช้แบบไดนามิก[ h ]และการประกอบเพื่อนำโค้ดกลับมาใช้ใหม่ การประกอบและการมอบหมายนั้นถูกทำให้เป็นอัตโนมัติโดยส่วนใหญ่ด้วยstructการฝัง ตามที่นักวิจัย Schmager et al. กล่าวไว้ คุณลักษณะนี้ "มีข้อเสียหลายประการของการสืบทอด: มันส่งผลกระทบต่ออินเทอร์เฟซสาธารณะของวัตถุ มันไม่ละเอียด (เช่น ไม่มีการควบคุมระดับเมธอดเหนือการฝัง) เมธอดของวัตถุที่ฝังอยู่ไม่สามารถซ่อนได้ และมันเป็นแบบคงที่" ทำให้ "ไม่ชัดเจน" ว่าโปรแกรมเมอร์จะใช้มันมากเกินไปในระดับที่โปรแกรมเมอร์ในภาษาอื่น ๆ มีชื่อเสียงว่าใช้การสืบทอดมากเกินไปหรือไม่[ 75 ]

ในตอนแรก Go ไม่ได้ จัดการข้อยกเว้นเนื่องจากขาด "การออกแบบที่ให้คุณค่าตามสัดส่วนของความซับซ้อน" [ 121 ] กลไก ที่คล้ายกับข้อยกเว้นpanicซึ่งrecoverหลีกเลี่ยงtry-catchโครงสร้างการควบคุมแบบปกติได้รับการเสนอ[ 122 ]และเผยแพร่ในสแนปช็อตเมื่อวันที่ 30 มีนาคม 2010 [ 123 ]ผู้เขียน Go แนะนำให้ใช้สำหรับข้อผิดพลาดที่ไม่สามารถกู้คืนได้ เช่น ข้อผิดพลาดที่ควรหยุดโปรแกรมทั้งหมดหรือคำขอเซิร์ฟเวอร์ หรือเป็นทางลัดในการส่งต่อข้อผิดพลาดขึ้นไปบนสแต็กภายในแพ็กเกจ[ 124 ] [ 125 ]ข้ามขอบเขตแพ็กเกจ Go มีประเภทข้อผิดพลาดมาตรฐาน และการส่งคืนค่าหลายค่าโดยใช้ประเภทนี้เป็นสำนวนมาตรฐาน[ 4 ]

สไตล์

ผู้เขียนโปรแกรม Go ได้ทุ่มเทความพยายามอย่างมากในการกำหนดรูปแบบของโปรแกรม Go:

  • เครื่องมือ นี้จะทำการกำหนดมาตรฐานการเยื้อง การเว้นวรรค และรายละเอียดระดับพื้นผิวอื่นๆ ของโค้ดโดยอัตโนมัติ โดยgofmtใช้แท็บสำหรับการเยื้องและช่องว่างสำหรับการจัดแนว การจัดแนวจะถือว่าโปรแกรมแก้ไขใช้ฟอนต์ที่มีความกว้างคงที่[ 126 ]golintจะทำการตรวจสอบสไตล์เพิ่มเติมโดยอัตโนมัติ แต่ถูกยกเลิกและเก็บถาวรโดยผู้ดูแล Go แล้ว[ 127 ]
  • เครื่องมือและไลบรารีที่แจกจ่ายพร้อมกับ Go แนะนำแนวทางมาตรฐานสำหรับสิ่งต่างๆ เช่น เอกสาร API ( godoc), [ 128 ]การทดสอบ ( go test), การสร้าง ( go build), การจัดการแพ็กเกจ ( go get) และอื่นๆ
  • Go บังคับใช้กฎที่เป็นคำแนะนำในภาษาอื่น ตัวอย่างเช่น ห้ามการพึ่งพาแบบวนซ้ำ ตัวแปรที่ไม่ได้ใช้[ 129 ]หรือการนำเข้า[ 130 ]และการแปลงประเภทโดยปริยาย
  • การละเว้นคุณลักษณะบางอย่าง (ตัวอย่างเช่น ทางลัดในการเขียนโปรแกรมเชิงฟังก์ชัน เช่น และบล็อก / mapแบบ Java ) มีแนวโน้มที่จะส่งเสริมรูปแบบการเขียนโปรแกรมที่ชัดเจน เป็นรูปธรรม และเชิงคำสั่งเป็นพิเศษtryfinally
  • ในวันแรก ทีม Go ได้เผยแพร่ชุดสำนวน Go [ 128 ]และต่อมายังได้รวบรวมความคิดเห็นการตรวจสอบโค้ด[ 131 ]การพูดคุย[ 132 ]และโพสต์บล็อกอย่างเป็นทางการ[ 133 ]เพื่อสอนสไตล์ Go และปรัชญาการเขียนโค้ด

เครื่องมือ

ชุดโปรแกรม Go หลักประกอบด้วยเครื่องมือสำหรับการสร้างทดสอบและวิเคราะห์โค้ด :

  • go buildซึ่งสร้างไบนารี Go โดยใช้ข้อมูลที่มีอยู่ในไฟล์ต้นฉบับเท่านั้น ไม่ต้องใช้ไฟล์ makefile แยกต่างหาก
  • go testสำหรับการทดสอบหน่วย การทดสอบประสิทธิภาพระดับไมโคร และการทดสอบแบบฟัซซิ่ง
  • go fmtสำหรับการจัดรูปแบบโค้ด
  • go installสำหรับการดึงและติดตั้งแพ็กเกจระยะไกล
  • go vetเครื่องมือวิเคราะห์แบบคงที่ที่มองหาข้อผิดพลาดที่อาจเกิดขึ้นในโค้ด
  • go runซึ่งเป็นทางลัดสำหรับการสร้างและเรียกใช้โค้ด
  • go docสำหรับการแสดงเอกสาร
  • go generateซึ่งเป็นวิธีมาตรฐานในการเรียกใช้ตัวสร้างโค้ด
  • go modสำหรับการสร้างโมดูลใหม่ การเพิ่มการพึ่งพา การอัปเกรดการพึ่งพา ฯลฯ
  • go toolสำหรับการเรียกใช้เครื่องมือสำหรับนักพัฒนา (เพิ่มใน Go เวอร์ชัน 1.24)

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

เครื่องมืออีกอย่างที่ทีม Go ดูแลรักษาแต่ไม่ได้รวมอยู่ในการแจกจ่าย Go คือgoplsเซิร์ฟเวอร์ภาษาที่ให้ คุณสมบัติ IDEเช่นการเติมโค้ดอัจฉริยะให้ กับ ตัวแก้ไขที่เข้ากันได้กับLanguage Server Protocol [ 134 ]

ระบบนิเวศของเครื่องมือจากผู้พัฒนาภายนอกช่วยเสริมการแจกจ่ายมาตรฐาน เช่นgocodeซึ่งช่วยให้สามารถเติมโค้ดอัตโนมัติในโปรแกรมแก้ไขข้อความหลายโปรแกรมgoimportsซึ่งจะเพิ่ม/ลบการนำเข้าแพ็กเกจโดยอัตโนมัติเมื่อจำเป็น และerrcheckซึ่งจะตรวจจับโค้ดที่อาจละเลยข้อผิดพลาดโดยไม่ได้ตั้งใจ

ตัวอย่าง

สวัสดีโลก

แพ็คเกจหลักนำเข้า"fmt"func main () { fmt.Println ( " hello world " ) }

โดยที่ "fmt" คือแพ็กเกจสำหรับการจัดรูปแบบI/Oคล้ายกับ<stdio.h> ของภาษา C หรือ<print> ของภาษา C++ [ 135 ]

ความพร้อมกัน

โปรแกรมง่ายๆ ต่อไปนี้แสดงให้เห็นถึงคุณสมบัติการทำงานพร้อมกัน ของ Go ในการใช้งานโปรแกรมแบบอะซิงโครนัส โดยจะเรียกใช้เธรดขนาดเล็กสองเธรด ("goroutines"): เธรดหนึ่งรอให้ผู้ใช้พิมพ์ข้อความ ในขณะที่อีกเธรดหนึ่งใช้การหมดเวลา คำสั่ง selectจะรอให้ goroutine ใด goroutine หนึ่งส่งข้อความไปยังรูทีนหลัก และดำเนินการกับข้อความแรกที่มาถึง (ตัวอย่างดัดแปลงมาจากหนังสือของ David Chisnall) [ 99 ] : 152

แพ็คเกจหลักนำเข้า( "fmt" "time" )func readword ( ch chan string ) { fmt . Println ( "พิมพ์คำ แล้วกด Enter." ) var word string fmt . Scanf ( "%s" , & word ) ch <- word }func timeout ( t chan bool ) { time . Sleep ( 5 * time . Second ) t <- false }func main () { t := make ( chan bool ) go timeout ( t )ch := make ( chan string ) go readword ( ch )เลือก{ กรณีคำ:= < - ch : fmt.Println ( " ได้ รับ" , คำ) กรณี<- t : fmt.Println ( " หมดเวลา" ) } }

การทดสอบ

แพ็คเกจการทดสอบให้การสนับสนุนการทดสอบอัตโนมัติของแพ็คเกจ Go [ 136 ]ตัวอย่างฟังก์ชันเป้าหมาย:

func ExtractUsername ( email string ) string { at := strings.Index ( email , " @" ) return email [ : at ] }

โค้ดทดสอบ (โปรดทราบว่าไม่มีคีย์เวิร์ด assert ใน Go; การทดสอบอยู่ในไฟล์ <filename>_test.go ในแพ็กเกจเดียวกัน):

นำเข้า( "การทดสอบ" )func TestExtractUsername ( t * testing . T ) { t . Run ( "withoutDot" , func ( t * testing . T ) { username := ExtractUsername ( "[email protected]" ) if username != "r" { t . Fatalf ( "Got: %v\n" , username ) } })t.Run ( " withDot" , func ( t * testing.T ) { username := ExtractUsername ( "[email protected]" ) if username != "jonh.smith" { t.Fatalf ( " Got: %v \ n " , username ) } } ) }

สามารถทำการทดสอบแบบขนานได้

แอปพลิเคชันบนเว็บ

แพ็คเกจ net /http [ 137 ]ให้การสนับสนุนสำหรับการสร้างเว็บแอปพลิเคชัน

ตัวอย่างนี้จะแสดงข้อความ "Hello world!" เมื่อเข้าชม localhost:8080

แพ็คเกจหลักimport ( "fmt" "log" "net/http" )func helloFunc ( w http . ResponseWriter , r * http . Request ) { fmt . Fprintf ( w , "Hello world!" ) }func main () { http.HandleFunc ( " / " , helloFunc ) log.Fatal ( http.ListenAndServe ( " : 8080 " , nil ) ) }

แอปพลิเคชัน

Go ได้รับการยอมรับอย่างกว้างขวางในโดเมนต่างๆ เนื่องจากมีไลบรารีมาตรฐานที่แข็งแกร่งและใช้งานง่าย[ 138 ]

แอปพลิเคชันยอดนิยม ได้แก่:

  • Caddy — เว็บเซิร์ฟเวอร์ที่ทำให้กระบวนการตั้งค่า HTTPS เป็นไปโดยอัตโนมัติ[ 139 ]
  • Docker — แพลตฟอร์มสำหรับการสร้างคอนเทนเนอร์ โดยมีเป้าหมายเพื่อลดความซับซ้อนของการพัฒนาและการใช้งานซอฟต์แวร์[ 140 ]
  • Kubernetes — ทำให้การปรับใช้ การปรับขนาด และการจัดการแอปพลิเคชันคอนเทนเนอร์เป็นไปโดยอัตโนมัติ[ 141 ]
  • CockroachDB — ฐานข้อมูล SQL แบบกระจายที่ออกแบบมาเพื่อความสามารถในการปรับขนาดและความสอดคล้องที่แข็งแกร่ง[ 142 ]
  • Hugo — เครื่องมือสร้างเว็บไซต์แบบคงที่ที่ให้ความสำคัญกับความเร็วและความยืดหยุ่น ช่วยให้นักพัฒนาสามารถสร้างเว็บไซต์ได้อย่างมีประสิทธิภาพ[ 143 ]

แผนกต้อนรับ

ระบบอินเทอร์เฟซและการละเว้นการสืบทอดโดยเจตนาได้รับการยกย่องจาก Michele Simionato ซึ่งเปรียบเทียบคุณลักษณะเหล่านี้กับคุณลักษณะของStandard MLโดยกล่าวว่า "เป็นเรื่องน่าเสียดายที่ไม่มีภาษาที่เป็นที่นิยมใดปฏิบัติตามเส้นทางเฉพาะนี้" [ 144 ]

Dave Astels จากEngine Yardเขียนไว้ในปี 2009 ว่า: [ 145 ]

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

ภาษาโกได้รับการตั้งชื่อให้เป็นภาษาโปรแกรมแห่งปีโดยดัชนีชุมชนการเขียนโปรแกรม TIOBEในปีแรกคือปี 2009 เนื่องจากมีความนิยมเพิ่มขึ้นมากกว่าภาษาอื่น ๆ ในปีนั้น (ภายในเวลาเพียง 2 เดือนหลังจากการเปิดตัวในเดือนพฤศจิกายน) และขึ้นมาอยู่ในอันดับที่ 13 ในเดือนมกราคม 2010 [ 146 ]แซงหน้าภาษาที่ได้รับการยอมรับอย่างPascalแต่ในเดือนมิถุนายน 2015 อันดับของภาษาโกตกลงมาต่ำกว่าอันดับที่ 50 ในดัชนี ทำให้ต่ำกว่าCOBOLและFortran [ 147 ] แต่ในเดือนมกราคม 2017 อันดับของภาษาโกก็พุ่งขึ้นมาอยู่ที่อันดับที่ 13 ซึ่งแสดงให้เห็นถึงการเติบโตอย่างมีนัยสำคัญในด้านความนิยมและการนำไปใช้ ภาษาโกจึงได้รับรางวัลภาษาโปรแกรมแห่งปีของ TIOBE อีกครั้งในปี 2016 [ 148 ]

Bruce Eckelได้กล่าวไว้ว่า: [ 149 ]

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

จากการประเมินภาษาและระบบจัดการหน่วยความจำ อัตโนมัติ (gc)ของภาษาดังกล่าว เปรียบเทียบกับ C++ ( GCC ), Java และScalaโดยวิศวกรของ Google ในปี 2011 พบว่า:

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

— อาร์. ฮุนด์ท[ 150 ]

การประเมินดังกล่าวได้รับการโต้แย้งจากทีมพัฒนา Go เอียน แลนซ์ เทย์เลอร์ ผู้ซึ่งได้ปรับปรุงโค้ด Go สำหรับบทความของฮุนดท์ ไม่ทราบถึงเจตนาที่จะเผยแพร่โค้ดของเขา และกล่าวว่าเวอร์ชันของเขา "ไม่เคยมีเจตนาที่จะเป็นตัวอย่างของ Go ที่เป็นแบบฉบับหรือมีประสิทธิภาพ" จากนั้นรัสส์ ค็อกซ์จึงทำการปรับปรุงโค้ด Go เช่นเดียวกับโค้ด C++ และทำให้โค้ด Go ทำงานได้เร็วเกือบเท่าเวอร์ชัน C++ และเร็วกว่าโค้ดในบทความมากกว่าหนึ่งเท่าตัว[ 151 ]

  • ค่า nilของ Go รวมกับการขาดประเภทพีชคณิตทำให้การจัดการความล้มเหลวและกรณีพื้นฐานทำได้ ยาก [ 152 ] [ 153 ]
  • Go ได้รับการวิพากษ์วิจารณ์ว่ามุ่งเน้นไปที่ความเรียบง่ายในการใช้งานมากกว่าความถูกต้องและความยืดหยุ่น ตัวอย่างเช่น ภาษาใช้ ความหมายของไฟล์ POSIXบนทุกแพลตฟอร์ม ดังนั้นจึงให้ข้อมูลที่ไม่ถูกต้องบนแพลตฟอร์มเช่นWindows (ซึ่งไม่เป็นไปตามมาตรฐานดังกล่าว) [ 154 ] [ 155 ]
  • การศึกษาแสดงให้เห็นว่าการเกิดข้อผิดพลาดในการทำงานพร้อมกันด้วยการส่งข้อความนั้นง่ายพอๆ กับการใช้หน่วยความจำร่วมกัน บางครั้งอาจง่ายกว่าด้วยซ้ำ[ 156 ]

ข้อพิพาทเรื่องการตั้งชื่อ

เมื่อวันที่ 10 พฤศจิกายน 2552 ซึ่งเป็นวันเปิดตัวภาษาอย่างเป็นทางการ ฟรานซิส แมคเคบ ผู้พัฒนาภาษาโปรแกรม Go! (โปรดสังเกตเครื่องหมายอัศเจรีย์) ได้ขอให้เปลี่ยนชื่อภาษาของ Google เพื่อป้องกันความสับสนกับภาษาของเขา ซึ่งเขาใช้เวลาพัฒนามา 10 ปี[ 157 ]แมคเคบแสดงความกังวลว่า "คนใหญ่คนโตจะบดขยี้" เขาในที่สุด และความกังวลนี้ก็สะท้อนกับนักพัฒนามากกว่า 120 คนที่แสดงความคิดเห็นในกระทู้ปัญหาอย่างเป็นทางการของ Google โดยกล่าวว่าพวกเขาควรเปลี่ยนชื่อ โดยบางคน[ 158 ]ถึงกับกล่าวว่าปัญหานี้ขัดแย้งกับคำขวัญของ Google ที่ว่า: อย่าทำชั่ว[ 159 ]

เมื่อวันที่ 12 ตุลาคม 2553 ตั๋วแจ้งปัญหาที่เปิดเผยต่อสาธารณะถูกปิดโดย Russ Cox (@rsc) นักพัฒนาของ Google โดยใช้ป้ายกำกับที่กำหนดเองว่า "น่าเสียดาย" พร้อมกับความคิดเห็นดังต่อไปนี้:

"มีผลิตภัณฑ์และบริการคอมพิวเตอร์มากมายที่มีชื่อว่า Go ในช่วง 11 เดือนนับตั้งแต่ที่เราเปิดตัว มีความสับสนระหว่างสองภาษาน้อยมาก" [ 159 ]

ดูเพิ่มเติม

หมายเหตุ

  1. ^แต่ "เพื่อให้ข้อความที่ซับซ้อนสามารถอยู่ในบรรทัดเดียวได้ อาจละเว้นเครื่องหมายเซมิโคลอนก่อนเครื่องหมายปิด ) หรือ }" [ 57 ]
  2. ^ "หากขึ้นบรรทัดใหม่หลังจากโทเค็นที่สามารถจบคำสั่งได้ [ตัวแยกวิเคราะห์จะ] แทรกเครื่องหมายเซมิโคลอน" [ 58 ]
  3. ^โดยปกติแล้ว ค่าผลลัพธ์หรือค่าข้อผิดพลาดจะมีค่าอย่างน้อยหนึ่งค่าที่ไม่ใช่ค่าศูนย์ของชนิดข้อมูลนั้น บางครั้งทั้งสองค่าอาจมีค่าอื่นที่ไม่ใช่ศูนย์ เช่น เมื่อการอ่านหรือการเขียนเสร็จสมบูรณ์เพียงบางส่วน และบางครั้งอาจไม่มีค่าอื่นที่ไม่ใช่ศูนย์เลย เช่น เมื่อการอ่านส่งคืนค่า 0 ไบต์ ดูคืนหลายค่า
  4. ^ a bคำถามที่พบบ่อยเกี่ยวกับภาษา "ทำไมจึงไม่มีการคำนวณเลขชี้กำลัง? ความปลอดภัย ... ไม่มีทางที่จะได้ที่อยู่ที่ไม่ถูกต้องซึ่งสำเร็จอย่างไม่ถูกต้อง ... การใช้ดัชนีอาร์เรย์สามารถมีประสิทธิภาพได้เท่ากับ ... การคำนวณเลขชี้กำลัง ... ทำให้การใช้งานตัวเก็บขยะง่ายขึ้น..." [ 4 ]
  5. ^คำถามที่พบบ่อยเกี่ยวกับภาษา "ทำไม Go ถึงไม่มี assertions? ...ประสบการณ์ของเราพบว่าโปรแกรมเมอร์ใช้ assertions เป็นเครื่องมือช่วยเพื่อหลีกเลี่ยงการคิดเกี่ยวกับการจัดการและการรายงานข้อผิดพลาดที่เหมาะสม..." [ 4 ]
  6. ^คำถามที่พบบ่อยเกี่ยวกับภาษา "ทำไมจึงไม่มีสหภาพที่ไม่มีแท็ก...? [พวกมัน] จะละเมิดการรับประกันความปลอดภัยของหน่วยความจำของ Go" [ 4 ]
  7. ^คำถามที่พบบ่อยเกี่ยวกับภาษา "ทำไม Go ถึงไม่มีประเภทตัวแปร? ... เราพิจารณา [พวกมัน] แต่พวกมันทับซ้อนกันในลักษณะที่สับสนกับอินเทอร์เฟซ.... [บาง] สิ่งที่ประเภทตัวแปรกล่าวถึงนั้นครอบคลุมอยู่แล้ว ... แม้ว่าจะไม่สง่างามเท่า" [ 4 ] (แท็กของประเภทอินเทอร์เฟซ [ 118 ]สามารถเข้าถึงได้ด้วยการยืนยันประเภท [ 119 ] )
  8. ^คำถาม "ฉันจะเรียกใช้เมธอดแบบไดนามิกได้อย่างไร" และ "ทำไมจึงไม่มีการสืบทอดประเภท" ในคำถามที่พบบ่อยของภาษา [ 4 ]

อ่านเพิ่มเติม

  • โดโนแวน, อลัน; เคอร์นิแกน, ไบรอัน (ตุลาคม 2015). ภาษาการเขียนโปรแกรมโก (ฉบับพิมพ์ครั้งที่ 1). แอดดิสัน-เวสลีย์ โปรเฟสชันแน ล . หน้า 400. ISBN 978-0-13-419044-0.
  • บอดเนอร์, จอน (มีนาคม 2021). การเรียนรู้เกมโกะ (ฉบับพิมพ์ครั้งที่ 1). โอไรลีย์ . หน้า 352. ISBN 9781492077213.
  • เว็บไซต์อย่างเป็นทางการแก้ไขข้อมูลนี้ได้ที่วิกิดาต้า
ดึงข้อมูลมาจาก " https://en.wikipedia.org/w/index.php?title=Go_(programming_language)&oldid=1359951441 "

สรุปเนื้อหา

ข้อมูลสำคัญจากบทความ

ข้อมูลสำคัญเกี่ยวกับ โก (ภาษาโปรแกรม)

Go เป็น ภาษาโปรแกรม ระดับ สูง อเนกประสงค์ ที่มี การกำหนดประเภทแบบคงที่ และ คอมไพล์...

ประวัติศาสตร์

Go ได้รับการออกแบบที่ Google ในปี 2550 เพื่อปรับปรุง ประสิทธิภาพการเขียนโปรแกรม ในยุคของ เครื่อง มัลติคอร์ เครื่อง เครือ ข่าย และ โค้ดเบส ขนาดใหญ่ [ 23 ] นักออกแบบต้องการแก้ไขข้อวิจารณ์ของภาษาอื่นๆ ที่ใช้ใน Google แต่ยังคงรักษาคุณลักษณะที่เป็นประโยชน์ไว้ [ 24...

การสร้างแบรนด์และการออกแบบ

มา สคอต ตัวตุ่น ถูกนำมาใช้ในปี 2009 สำหรับ การเปิด ตัว ภาษาแบบโอ เพนซอร์ส Renée French ผู้ซึ่งออกแบบมาสคอตกระต่ายสำหรับ Plan 9 ได้ดัดแปลงมาสคอตตัวตุ่นจากแบบเสื้อยืด WFMU รุ่นก่อนหน้า [ 34 ]

ยาสามัญ

การขาดการสนับสนุน การเขียนโปรแกรมแบบเจเนริก ในเวอร์ชันเริ่มต้นของ Go ได้รับการวิพากษ์วิจารณ์อย่างมาก [ 38 ] นักออกแบบแสดงความเปิดกว้างต่อการเขียนโปรแกรมแบบเจเนริกและสังเกตว่าฟังก์ชันในตัวนั้น เป็น แบบเจเนริกตามประเภท แต่ได้รับการปฏิบัติเหมือนเป็นกรณีพิเศษ...