วิธีหลีกเลี่ยงข้อผิดพลาดที่น่ารำคาญ“ ประกาศและไม่ใช้แล้ว”


238

ฉันกำลังเรียนรู้ไป แต่ฉันรู้สึกว่ามันน่ารำคาญเล็กน้อยเมื่อรวบรวมฉันไม่ควรปล่อยให้ตัวแปรหรือแพ็กเกจที่ไม่ได้ใช้

นี่มันทำให้ฉันช้าลงจริงๆ ตัวอย่างเช่นฉันแค่ต้องการประกาศแพ็คเกจใหม่และวางแผนที่จะใช้ในภายหลังหรือเพียงแค่แสดงข้อคิดเห็นคำสั่งเพื่อทดสอบ ฉันมักจะได้รับข้อผิดพลาดและจำเป็นต้องแสดงความคิดเห็นการใช้งานเหล่านั้นทั้งหมด

มีวิธีใดบ้างในการหลีกเลี่ยงการเช็คอินแบบนี้หรือไม่?


1
คุณยังสามารถใช้ goimports ( godoc.org/code.google.com/p/go.tools/cmd/goimports ) เพื่อเพิ่ม / ลบการนำเข้าให้คุณโดยอัตโนมัติ
elithrar


3
ฉันยังรู้สึกว่าตัวเลือกคอมไพเลอร์จะเป็นประโยชน์สำหรับเวิร์กโฟลว์ "ฉันต้องการที่จะแสดงความคิดเห็นบางสิ่งบางอย่างเพื่อช่วยในการแก้จุดบกพร่อง" เวิร์กโฟลว์
RJFalconer

13
คุณลักษณะนี้เป็นวิธีที่ยอดเยี่ยมในการเสียเวลาของผู้คนครับประเด็นคืออะไร? เมื่อคุณยอมรับ / ส่งรหัส ok ไม่มี vars ที่ไม่ได้ใช้ดี แต่เมื่อพัฒนามัน? น่ากลัว
Alexander Mills

มันเป็นปี 2020 และฉันไม่สามารถเชื่อได้ว่าพวกเขายังไม่ได้แก้ไขปัญหานี้ (แม้จะมีธงคอมไพเลอร์) ฉันทำโครงการใน Go ประมาณ 5 ปีที่แล้วและโดยรวมก็ชอบภาษา แต่มันก็ใช้ไม่ได้สำหรับฉันเพราะสิ่งนี้ วิธีที่ฉันใช้รหัสฉันแสดงความคิดเห็นอย่างต่อเนื่อง / ไม่แสดงความคิดเห็นดังนั้น "ฟีเจอร์" ใน Go ทำให้ทุกอย่างใช้เวลาสองเท่าสำหรับฉัน ... ฉันได้ตรวจสอบทุกสองสามเดือนนับ แต่นั้นมาเพื่อดูว่ามีเหตุผลอะไรบ้าง ทีม Go และยังไม่มีโชคเลย ... มันเป็นภาษาที่ยอดเยี่ยมเป็นอย่างอื่นและฉันก็ชอบที่จะใช้มันมากกว่านี้ แต่ในปัจจุบันมันไม่สามารถใช้งานได้สำหรับฉัน
Ruslan

คำตอบ:


234

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

แต่ถ้าคุณต้องการข้ามข้อผิดพลาดนี้จริงๆคุณสามารถใช้ตัวระบุที่ว่างเปล่า ( _):

package main

import (
    "fmt" // imported and not used: "fmt"
)

func main() {
    i := 1 // i declared and not used
}

กลายเป็น

package main

import (
    _ "fmt" // no more error
)

func main() {
    i := 1 // no more error
    _ = i
}

ตามที่กล่าวโดย kostix ในความคิดเห็นด้านล่างคุณสามารถค้นหาตำแหน่งอย่างเป็นทางการของทีม Go ในคำถามที่พบบ่อย :

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


90
แต่ถึงกระนั้นก็ไม่ได้แตกต่างจากการออกความเห็น และฉันเข้าใจว่านี่เป็นรหัสที่ดีกว่า แต่มันจะดีกว่าถ้าเราสามารถปิดการตรวจสอบว่าทำไมการทดสอบรหัสของเราแล้วเปิดการตรวจสอบนี้อีกครั้งหลังจากที่เราต้องการเสร็จรหัสและทำให้มันสะอาด?
A-letubby

21
@ kostix เอ่อ .. มันอาจไม่ทำให้คุณช้าลงเพราะคุณอาจเป็นผู้เชี่ยวชาญ แต่มันสำหรับฉันและวิธีที่ฉันเขียนโปรแกรม ฉันแค่สงสัยว่ามีวิธีที่ดีกว่า แต่อย่างไรก็ตามขอบคุณสำหรับคำถามที่พบบ่อย! จากการอ่านสิ่งนี้ฉันเข้าใจได้อย่างสมบูรณ์ว่าเหตุผลใดที่ golang กำลังทำเช่นนี้
A-letubby

20
มีอาร์กิวเมนต์บรรทัดคำสั่งเพื่อปิดนี้หรือไม่ หรือนี่เป็นคุณสมบัติที่ไม่สามารถเปลี่ยนแปลงได้?
Ethan Bierlein

26
FWIW ฉันมีช่วงเวลาที่เลวร้ายในการอ่านรหัสของผู้อื่น แต่ไม่แน่นอนเนื่องจากสัญลักษณ์ที่ไม่ได้ใช้ OTOH ฉันเสียเวลาหนึ่งชั่วโมงในการตรวจสอบวิธีการเพื่อจัดการกับคุณลักษณะ "#" $ * golang นี้
Torsten Bronger

24
น่าเศร้าคำตอบนี้ถูกต้อง - แต่นั่นไม่ได้พิสูจน์ให้เห็นถึงมัน มีโลกที่แตกต่างระหว่างการตรวจสอบรหัสและเพียงแค่ดำเนินการ เมื่อเราตรวจสอบรหัสเราใช้ linters เพื่อตรวจจับข้อผิดพลาดชนิดนี้ เมื่อเราดำเนินการในระหว่างการพัฒนาอย่างรวดเร็วเราไม่มีมาตรฐานเดียวกัน ไม่สามารถให้อภัยคอมไพเลอร์กับ linter ได้ แม้แต่ตำรวจสไตล์ใน Google ก็ไม่ได้ทำผิด
Travis Wilson

29

คุณสามารถใช้ฟังก์ชัน "null" แบบง่ายเช่นนี้:

func Use(vals ...interface{}) {
    for _, val := range vals {
        _ = val
    }
}

ซึ่งคุณสามารถใช้เช่น:

package main

func main() {
    a := "declared and not used"
    b := "another declared and not used"
    c := 123

    Use(a, b, c)
}

นอกจากนี้ยังมีแพ็กเกจสำหรับสิ่งนี้เพื่อให้คุณไม่จำเป็นต้องกำหนดUseฟังก์ชั่นทุกครั้ง:

import (
  "github.com/lunux2008/xulu"
)

func main() {
  // [..]

  xulu.Use(a, b, c)
}

29

ตามคำถามที่พบบ่อย :

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

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

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

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

# Install it
$ go get golang.org/x/tools/cmd/goimports

# -w to write the source file instead of stdout
$ goimports -w my_file.go

คุณควรจะสามารถรันสิ่งนี้จากโปรแกรมแก้ไขที่ดีครึ่งทาง - ตัวอย่างเช่นสำหรับ Vim:

:!goimports -w %

goimportsรายการหน้าคำสั่งบางอย่างสำหรับบรรณาธิการอื่น ๆ และคุณมักจะกำหนดให้มีการทำงานโดยอัตโนมัติเมื่อคุณบันทึกบัฟเฟอร์ไปยังดิสก์

โปรดทราบว่ายังจะทำงานgoimportsgofmt


ดังที่ได้กล่าวไปแล้วสำหรับตัวแปรวิธีที่ง่ายที่สุดคือ (ชั่วคราว) กำหนดให้กับ_:

// No errors
tasty := "ice cream"
horrible := "marmite"

// Commented out for debugging
//eat(tasty, horrible)

_, _ = tasty, horrible

9

มุมหนึ่งที่ไม่ได้กล่าวถึงคือชุดเครื่องมือที่ใช้สำหรับการแก้ไขโค้ด

การใช้Visual Studio Codeพร้อมกับส่วนขยายจากlukehoban ที่เรียกว่าGoจะทำให้คุณมีเวทมนตร์อัตโนมัติ ส่วนขยายไปทำงานโดยอัตโนมัติgofmt, golintฯลฯ และลบและเพิ่มimportรายการ อย่างน้อยตอนนี้ก็เป็นอัตโนมัติ

ฉันจะยอมรับว่าไม่ใช่ 100% ของการแก้ปัญหา แต่ก็มีประโยชน์พอ


8

ในกรณีที่คนอื่นรู้สึกลำบากในเรื่องนี้ฉันคิดว่ามันอาจช่วยอธิบายได้อย่างตรงไปตรงมา หากคุณมีตัวแปรที่คุณไม่ได้ใช้เช่นฟังก์ชั่นที่คุณได้คอมเม้นต์การเรียกใช้ (กรณีการใช้งานทั่วไป):

myFn := func () { }
// myFn()

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

myFn := func () { }
_ = myFn
// myFn()
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.