portaldacalheta.pt
  • หลัก
  • การจัดการวิศวกรรม
  • Kpi และ Analytics
  • เทคโนโลยี
  • ว่องไว
ส่วนหลัง

4 คำติชมของ Go Language



Go (a.k.a. Golang) เป็นหนึ่งในภาษาที่ผู้คนให้ความสนใจมากที่สุด ณ เดือนเมษายน 2018 อยู่ในอันดับที่ 19 ในดัชนี TIOBE . ผู้คนจำนวนมากขึ้นเรื่อย ๆ เปลี่ยนจาก PHP, Node.js และภาษาอื่น ๆ มาใช้ Go และใช้มันในการผลิต ซอฟต์แวร์เจ๋ง ๆ มากมาย (เช่น Kubernetes, Docker และ Heroku CLI) เขียนโดยใช้ Go

แล้วอะไรคือกุญแจสู่ความสำเร็จของ Go? มีหลายสิ่งหลายอย่างภายในภาษาที่ทำให้มันเจ๋งมาก แต่สิ่งสำคัญอย่างหนึ่งที่ทำให้มันเป็นที่นิยมอย่าง“ ฉันไปสู่ความเรียบง่าย” ตามที่ผู้สร้างคนหนึ่งกล่าวไว้ ร็อบไพค์ .



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



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



คำติชม 4 ประการของภาษา Go

1. ขาดฟังก์ชันโอเวอร์โหลดและค่าดีฟอลต์สำหรับอาร์กิวเมนต์

ฉันจะโพสต์ตัวอย่างโค้ดจริงที่นี่ เมื่อฉันทำงานกับการเชื่อม Golang Selenium ฉันจำเป็นต้องเขียนฟังก์ชันที่มีพารามิเตอร์สามตัว สองคนเป็นทางเลือก นี่คือสิ่งที่ดูเหมือนว่าหลังจากการปรับใช้:

func (wd *remoteWD) WaitWithTimeoutAndInterval(condition Condition, timeout, interval time.Duration) error { // the actual implementation was here } func (wd *remoteWD) WaitWithTimeout(condition Condition, timeout time.Duration) error { return wd.WaitWithTimeoutAndInterval(condition, timeout, DefaultWaitInterval) } func (wd *remoteWD) Wait(condition Condition) error { return wd.WaitWithTimeoutAndInterval(condition, DefaultWaitTimeout, DefaultWaitInterval) }

ฉันต้องใช้ฟังก์ชันที่แตกต่างกันสามฟังก์ชันเพราะฉันไม่สามารถโอเวอร์โหลดฟังก์ชันหรือส่งผ่านค่าเริ่มต้นได้ - Go ไม่ได้จัดเตรียมไว้ตามการออกแบบ ลองนึกดูว่าจะเกิดอะไรขึ้นถ้าฉันโทรผิดโดยไม่ได้ตั้งใจ นี่คือตัวอย่าง:



มันจะทำให้ฉันมี

ฉันต้องยอมรับว่าบางครั้งการทำงานเกินพิกัดอาจส่งผลให้โค้ดยุ่งได้ ในทางกลับกันด้วยเหตุนี้โปรแกรมเมอร์จึงต้องเขียนโค้ดมากขึ้น



จะปรับปรุงได้อย่างไร

นี่คือตัวอย่างเดียวกัน (ดีเกือบเหมือนกัน) ใน JavaScript:

function Wait (condition, timeout = DefaultWaitTimeout, interval = DefaultWaitInterval) { // actual implementation here }

อย่างที่คุณเห็นมันดูชัดเจนขึ้นมาก



ฉันชอบวิธี Elixir ด้วยเช่นกัน นี่คือลักษณะที่ปรากฏใน Elixir (ฉันรู้ว่าคุณสามารถใช้ค่าเริ่มต้นได้เช่นในตัวอย่างด้านบนฉันแค่แสดงให้เห็นว่าเป็นวิธีการทำ):

defmodule Waiter do @default_interval 1 @default_timeout 10 def wait(condition, timeout, interval) do // implementation here end def wait(condition, timeout), do: wait(condition, timeout, @default_interval) def wait(condition), do: wait(condition, @default_timeout, @default_interval) end Waiter.wait('condition', 2, 20) Waiter.wait('condition', 2) Waiter.wait('condition')

2. ขาดยาชื่อสามัญ

นี่เป็นคุณสมบัติที่ผู้ใช้ Go ถามหามากที่สุดอย่างไม่ต้องสงสัย



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

ลองทำเพื่อหาจำนวนเต็ม:



package main import 'fmt' func mapArray(arr []int, callback func (int) (int)) []int { newArray := make([]int, len(arr)) for index, value := range arr { newArray[index] = callback(value) } return newArray; } func main() { square := func(x int) int { return x * x } fmt.Println(mapArray([]int{1,2,3,4,5}, square)) // prints [1 4 9 16 25] }

ดูดีใช่มั้ย?

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

func mapArrayOfInts(arr []int, callback func (int) (int)) []int { // implementation } func mapArrayOfFloats(arr []float64, callback func (float64) (float64)) []float64 { // implementation } func mapArrayOfStrings(arr []string, callback func (string) (string)) []string { // implementation }

นั่นขัดกับหลักการ DRY ซึ่งระบุว่าคุณควรเขียนโค้ดคัดลอก / วางให้น้อยที่สุดเท่าที่จะเป็นไปได้และย้ายไปอยู่ในฟังก์ชันและใช้อีกครั้งแทน

การขาดยาชื่อสามัญหมายถึงฟังก์ชันที่แตกต่างกันหลายร้อยฟังก์ชัน

วิธีจัดการกับข้อยกเว้นในบริการเว็บที่สงบ

อีกวิธีหนึ่งคือการใช้การใช้งานเดี่ยวกับ interface {} เป็นพารามิเตอร์ แต่อาจส่งผลให้เกิดข้อผิดพลาดรันไทม์เนื่องจากการตรวจสอบประเภทรันไทม์มีแนวโน้มที่จะเกิดข้อผิดพลาดมากกว่า และจะช้าลงด้วยดังนั้นจึงไม่มีวิธีง่ายๆในการใช้ฟังก์ชันเหล่านี้เป็นหนึ่งเดียว

จะปรับปรุงได้อย่างไร

มีภาษาดีๆมากมายที่รวมถึงการสนับสนุนทั่วไป ตัวอย่างเช่นนี่คือรหัสเดียวกันใน Rust (ฉันใช้ vec แทน array เพื่อให้ง่ายขึ้น):

fn map(vec:Vec, callback:fn(T) -> T) -> Vec { let mut new_vec = vec![]; for value in vec { new_vec.push(callback(value)); } return new_vec; } fn square (val:i32) -> i32 { return val * val; } fn underscorify(val:String) -> String { return format!('_{}_', val); } fn main() { let int_vec = vec![1, 2, 3, 4, 5]; println!('{:?}', map::(int_vec, square)); // prints [1, 4, 9, 16, 25] let string_vec = vec![ 'hello'.to_string(), 'this'.to_string(), 'is'.to_string(), 'a'.to_string(), 'vec'.to_string() ]; println!('{:?}', map::(string_vec, underscorify)); // prints ['_hello_', '_this_', '_is_', '_a_', '_vec_'] }

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

3. การจัดการการพึ่งพา

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

คุณสามารถทำได้ดีขึ้นเล็กน้อยโดยใช้ Dep เพื่อจัดการการอ้างอิง ( https://github.com/golang/dep ) แต่ปัญหาคือคุณกำลังจัดเก็บการอ้างอิงทั้งหมดของคุณในที่เก็บของคุณ (ซึ่งไม่ดีเพราะที่เก็บของคุณจะไม่มีแค่รหัสของคุณเท่านั้น แต่ยังมีโค้ดอ้างอิงอีกหลายพันบรรทัด) หรือคุณจะเก็บรายการ ของแพ็กเกจ (แต่อีกครั้งหากผู้ดูแลการอ้างอิงทำการย้อนกลับ - การเปลี่ยนแปลงที่เข้ากันไม่ได้ทุกอย่างจะผิดพลาด)

จะปรับปรุงได้อย่างไร

ฉันคิดว่าตัวอย่างที่สมบูรณ์แบบในที่นี้คือ Node.js (และ JavaScript โดยทั่วไปฉันเดา) และ NPM NPM เป็นที่เก็บแพ็กเกจ มันจัดเก็บแพ็คเกจเวอร์ชันต่างๆดังนั้นหากคุณต้องการแพ็คเกจเวอร์ชันเฉพาะก็ไม่มีปัญหาคุณสามารถรับได้จากที่นั่น นอกจากนี้สิ่งหนึ่งในแอปพลิเคชัน Node.js / JavaScript คือไฟล์ package.json ที่นี่การอ้างอิงทั้งหมดและเวอร์ชันของพวกเขาจะแสดงรายการดังนั้นคุณสามารถติดตั้งได้ทั้งหมด (และรับเวอร์ชันที่ใช้งานได้กับโค้ดของคุณอย่างแน่นอน) ด้วย npm install

นอกจากนี้ตัวอย่างการจัดการแพ็คเกจที่ยอดเยี่ยม ได้แก่ RubyGems / Bundler (สำหรับแพ็คเกจ Ruby) และ Crates.io/Cargo (สำหรับไลบรารี Rust)

4. การจัดการข้อผิดพลาด

การจัดการข้อผิดพลาดใน Go นั้นง่ายมาก ใน Go คุณสามารถส่งคืนค่าฟังก์ชันได้หลายค่าและฟังก์ชันสามารถส่งคืนข้อผิดพลาดได้ สิ่งนี้:

err, value := someFunction(); if err != nil { // handle it somehow }

ทีนี้ลองนึกดูว่าคุณต้องเขียนฟังก์ชันที่ดำเนินการสามอย่างที่ส่งคืนข้อผิดพลาด จะมีลักษณะดังนี้:

func doSomething() (err, int) { err, value1 := someFunction(); if err != nil { return err, nil } err, value2 := someFunction2(value1); if err != nil { return err, nil } err, value3 := someFunction3(value2); if err != nil { return err, nil } return value3; }

มีรหัสที่ทำซ้ำได้จำนวนมากที่นี่ซึ่งไม่ดี และด้วยฟังก์ชั่นที่ยอดเยี่ยม มันอาจแย่กว่านั้น . คุณอาจต้องใช้คีย์บนแป้นพิมพ์สำหรับสิ่งนี้:

ภาพการ์ตูนของรหัสการจัดการข้อผิดพลาดบนแป้นพิมพ์

จะปรับปรุงได้อย่างไร

ฉันชอบวิธีการของ JavaScript ในเรื่องนั้น ฟังก์ชันนี้สามารถทำให้เกิดข้อผิดพลาดและคุณสามารถจับได้ ลองพิจารณาตัวอย่าง:

function doStuff() { const value1 = someFunction(); const value2 = someFunction2(value1); const value3 = someFunction3(value2); return value3; } try { const value = doStuff(); // do something with it } catch (err) { // handle the error }

ชัดเจนกว่ามากและไม่มีโค้ดที่ทำซ้ำได้สำหรับการจัดการข้อผิดพลาด

สิ่งที่ดีเกี่ยวกับ Go

แม้ว่า Go จะมีข้อบกพร่องมากมายจากการออกแบบ แต่ก็มีคุณสมบัติที่ยอดเยี่ยมจริงๆ

1. โกรูทีน

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

func doSomeCalculations() { // do some CPU intensive/long running tasks } func main() { go doSomeCalculations(); // This will run in another thread; }

2. เครื่องมือที่มาพร้อมกับ Go

ในขณะที่ภาษาโปรแกรมอื่น ๆ คุณต้องติดตั้งไลบรารี / เครื่องมือที่แตกต่างกันสำหรับงานที่แตกต่างกัน (เช่นการทดสอบการจัดรูปแบบโค้ดแบบคงที่ ฯลฯ ) มีเครื่องมือที่ยอดเยี่ยมมากมายที่รวมอยู่ใน Go ตามค่าเริ่มต้นแล้วเช่น

  • gofmt - เครื่องมือสำหรับการวิเคราะห์รหัสคงที่ เมื่อเปรียบเทียบกับ JavaScript ซึ่งคุณต้องติดตั้งการอ้างอิงเพิ่มเติมเช่น eslint หรือ jshint ที่นี่จะรวมไว้โดยค่าเริ่มต้น และโปรแกรมจะไม่คอมไพล์ด้วยซ้ำหากคุณไม่เขียนโค้ด Go-style (โดยไม่ใช้ตัวแปรที่ประกาศการนำเข้าแพ็คเกจที่ไม่ได้ใช้งาน ฯลฯ )
  • go test - กรอบการทดสอบ อีกครั้งเมื่อเปรียบเทียบกับ JavaScript คุณต้องติดตั้งการอ้างอิงเพิ่มเติมสำหรับการทดสอบ (Jest, Mocha, AVA และอื่น ๆ ) ที่นี่จะรวมไว้โดยปริยาย และยังช่วยให้คุณสามารถทำสิ่งดีๆมากมายตามค่าเริ่มต้นเช่นการเปรียบเทียบการแปลงรหัสในเอกสารประกอบเป็นการทดสอบเป็นต้น
  • godoc - เครื่องมือจัดทำเอกสาร ยินดีที่ได้รวมไว้ในเครื่องมือเริ่มต้น
  • คอมไพเลอร์นั่นเอง มันเร็วอย่างไม่น่าเชื่อเมื่อเทียบกับภาษาคอมไพล์อื่น ๆ !

3. เลื่อน

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

function openManyFiles() { let file1, file2, file3; try { file1 = open(‘path-to-file1’); } catch (err) { return; } try { file2 = open(‘path-to-file2’); } catch (err) { // we need to close first file, remember? close(file1); return; } try { file3 = open(‘path-to-file3’); } catch (err) { // and now we need to close both first and second file close(file1); close(file2); return; } // do some stuff with files // closing files after successfully processing them close(file1); close(file2); close(file3); return; }

ดูเหมือนซับซ้อน นั่นคือสิ่งที่ไป defer เข้ามาแทน:

package main import ( 'fmt' ) func openFiles() { // Pretending we’re opening files fmt.Printf('Opening file 1 '); defer fmt.Printf('Closing file 1 '); fmt.Printf('Opening file 2 '); defer fmt.Printf('Closing file 2 '); fmt.Printf('Opening file 3 '); // Pretend we've got an error on file opening // In real products, an error will be returned here. return; } func main() { openFiles() /* Prints: Opening file 1 Opening file 2 Opening file 3 Closing file 2 Closing file 1 */ }

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

ข้อสรุป

ฉันไม่ได้พูดถึงสิ่งที่ดีและไม่ดีทั้งหมดเกี่ยวกับ Go เพียงแค่สิ่งที่ฉันคิดว่าดีที่สุดและแย่ที่สุด

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

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

ในระหว่างนี้หากคุณกำลังพยายามปรับปรุงการทดสอบด้วย Go ให้ลอง ทดสอบแอป Go ของคุณ - เริ่มต้นใช้งานได้ทันที โดยเพื่อนร่วมงาน ApeeScape Gabriel Aszalos

วิธีการสร้างมูลค่าให้กับ Fintech Startup

นักลงทุนและเงินทุน

วิธีการสร้างมูลค่าให้กับ Fintech Startup
ฝึกฝนฝีมือของคุณด้วยเครื่องมือ UX ชั้นนำเหล่านี้

ฝึกฝนฝีมือของคุณด้วยเครื่องมือ UX ชั้นนำเหล่านี้

การออกแบบ Ux

โพสต์ยอดนิยม
Nvidia Shield - สิ่งที่แตกต่างบนคอนโซลเกม Android
Nvidia Shield - สิ่งที่แตกต่างบนคอนโซลเกม Android
แผ่นโกงการจัดการโครงการ
แผ่นโกงการจัดการโครงการ
เริ่มต้นใช้งาน Microservices: บทช่วยสอน Dropwizard
เริ่มต้นใช้งาน Microservices: บทช่วยสอน Dropwizard
การแยกการเรียกเก็บเงิน: เรื่องของการเพิ่มประสิทธิภาพ API ภายใน GraphQL
การแยกการเรียกเก็บเงิน: เรื่องของการเพิ่มประสิทธิภาพ API ภายใน GraphQL
กรณีศึกษา: การใช้ ApeeScape เพื่อม้วนปลาใหญ่
กรณีศึกษา: การใช้ ApeeScape เพื่อม้วนปลาใหญ่
 
การประมาณต้นทุนซอฟต์แวร์ในการจัดการโครงการแบบ Agile
การประมาณต้นทุนซอฟต์แวร์ในการจัดการโครงการแบบ Agile
แชทล่ม - เมื่อ Chatbot ล้มเหลว
แชทล่ม - เมื่อ Chatbot ล้มเหลว
ที่ปรึกษาการระดมทุนกับนายหน้า - ตัวแทนจำหน่าย
ที่ปรึกษาการระดมทุนกับนายหน้า - ตัวแทนจำหน่าย
ทำให้ Web Front-end เชื่อถือได้ด้วย Elm
ทำให้ Web Front-end เชื่อถือได้ด้วย Elm
คู่มือสำหรับนักลงทุนเกี่ยวกับน้ำมันปาล์ม
คู่มือสำหรับนักลงทุนเกี่ยวกับน้ำมันปาล์ม
โพสต์ยอดนิยม
  • วิธีแฮกบัตรเติมเงิน
  • วิธีการกำหนดราคาตัวเลือก
  • ข้อใดไม่ใช่จุดอ่อนที่อาจส่งผลต่อเว็บไซต์ของบริษัทออนไลน์
  • css สำหรับขนาดหน้าจอต่างๆ
  • ซื้อบัตรเครดิตออนไลน์จากแฮกเกอร์
หมวดหมู่
  • การจัดการวิศวกรรม
  • Kpi และ Analytics
  • เทคโนโลยี
  • ว่องไว
  • © 2022 | สงวนลิขสิทธิ์

    portaldacalheta.pt