จะแบ่งรหัสยาว ๆ ใน Golang ได้อย่างไร?


111

มาจาก Python ฉันไม่คุ้นเคยกับโค้ดไลน์ที่ยาวเกิน 80 คอลัมน์ ดังนั้นเมื่อฉันพบสิ่งนี้:

err := database.QueryRow("select * from users where user_id=?", id).Scan(&ReadUser.ID, &ReadUser.Name, &ReadUser.First, &ReadUser.Last, &ReadUser.Email)

ฉันพยายามที่จะทำลายมัน

err := database.QueryRow("select * from users where user_id=?", id) \
    .Scan(&ReadUser.ID, &ReadUser.Name, &ReadUser.First, &ReadUser.Last, &ReadUser.Email)

แต่ฉันเข้าใจ

 syntax error: unexpected \

ฉันยังลองแค่ทำลายเส้นด้วยการกดปุ่ม enter และใส่เครื่องหมายอัฒภาคที่ท้าย:

err := database.QueryRow("select * from users where user_id=?", id) 
.Scan(&ReadUser.ID, &ReadUser.Name, &ReadUser.First, &ReadUser.Last, &ReadUser.Email);

แต่ฉันได้รับอีกครั้ง:

syntax error: unexpected .

ดังนั้นฉันจึงสงสัยว่าวิธีโกแลงนิกทำอย่างไร?

คำตอบ:


124

ก่อนอื่นพื้นหลัง ไวยากรณ์ที่เป็นทางการของ Go ใช้อัฒภาค";"เป็นตัวยุติในการผลิตหลายรายการ แต่โปรแกรม Go อาจละเว้นส่วนใหญ่ (และควรมีแหล่งที่มาที่ชัดเจนและอ่านง่ายgofmtนอกจากนี้ยังลบอัฒภาคที่ไม่จำเป็นออกไปด้วย)

ข้อกำหนดแสดงรายการกฎที่แน่นอน Spec: อัฒภาค:

ไวยากรณ์อย่างเป็นทางการใช้อัฒภาค ";" ในฐานะผู้ยุติการผลิตในหลาย ๆ โปรดักชั่น โปรแกรม Go อาจละอัฒภาคเหล่านี้เกือบทั้งหมดโดยใช้กฎสองข้อต่อไปนี้:

  1. เมื่ออินพุตถูกแบ่งออกเป็นโทเค็นอัฒภาคจะถูกแทรกโดยอัตโนมัติในสตรีมโทเค็นทันทีหลังจากโทเค็นสุดท้ายของบรรทัดหากโทเค็นนั้น

  2. ในการอนุญาตให้คำสั่งที่ซับซ้อนครอบครองบรรทัดเดียวอัฒภาคอาจถูกละไว้ก่อนปิด ")" หรือ "}"

ดังที่คุณสามารถดูได้ว่าคุณแทรกอักขระขึ้นบรรทัดใหม่หลังวงเล็บ)หรือไม่อัฒภาค;จะถูกแทรกโดยอัตโนมัติดังนั้นบรรทัดถัดไปจะไม่ถือเป็นความต่อเนื่องของบรรทัดก่อนหน้า นี่คือสิ่งที่เกิดขึ้นในกรณีของคุณดังนั้นบรรทัดถัดไปที่เริ่มต้นด้วย.Scan(&ReadUser.ID,...จะทำให้คุณมีข้อผิดพลาดเวลาคอมไพล์ตามนี้เอง (โดยไม่มีบรรทัดก่อนหน้า) เป็นข้อผิดพลาดเวลาคอมไพล์:syntax error: unexpected .

ดังนั้นคุณอาจล้ำเส้นของคุณเมื่อใดก็ได้ที่ไม่ขัดแย้งกับกฎที่ระบุไว้ในจุด1.ข้างต้น

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

i := 1 +
        2
fmt.Println(i) // Prints 3

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

s := []int {
    1, 2, 3,
    4, 5, 6,  // Note it ends with a comma
}

เพื่อให้สอดคล้องกับกฎอัฒภาคและเพื่อให้คุณสามารถจัดเรียงและเพิ่มบรรทัดใหม่ได้โดยไม่ต้องดูแลการเพิ่ม / ลบเครื่องหมายจุลภาคสุดท้าย เช่นคุณสามารถสลับ 2 บรรทัดโดยไม่ต้องลบและเพิ่มลูกน้ำใหม่:

s := []int {
    4, 5, 6,
    1, 2, 3,
}

เช่นเดียวกับเมื่อแสดงรายการอาร์กิวเมนต์ในการเรียกใช้ฟังก์ชัน:

fmt.Println("first",
    "second",
    "third",       // Note it ends with a comma
)

3
ฉันใส่เครื่องหมายจุลภาคต่อท้ายตัวอักษรจาวาสคริปต์ #hatejs
Paulo Scardine

29
TL; DR: โดยทั่วไปคุณสามารถขีดเส้นหลังลูกน้ำหลังจากเปิดวงเล็บเช่น (, [, {, และหลังจุดซึ่งอาจอ้างอิงฟิลด์หรือวิธีการของค่าบางค่า
Peeter Kokk

2
การต้องเพิ่มเครื่องหมายจุลภาคพิเศษในตอนท้ายทำให้ฉันนึกถึงข้อบกพร่องของ IE js เก่า ๆ แย่มาก
Christophe Roussy

5
@ChristopheRoussy เป็นเรื่องส่วนตัวฉันรักเดียวที่ทุกบรรทัดต้องลงท้ายด้วยเครื่องหมายจุลภาคและฉันสามารถจัดเรียงและเพิ่มบรรทัดใหม่ได้อย่างง่ายดายโดยไม่ต้องดูแลการเพิ่ม / ลบเครื่องหมายจุลภาค
icza

@icza ฉันชอบให้พวกเขาลงท้ายด้วยลูกน้ำ แต่ไม่ต้องทำเพื่ออันสุดท้าย :)
Christophe Roussy

23

วิธีที่ง่ายที่สุดคือออกจากตัวดำเนินการ (. ) ในบรรทัดแรก

\ นอกจากนี้ยังไม่แนะนำให้ใช้ความต่อเนื่องของบรรทัดในคำแนะนำสไตล์ python คุณสามารถรวมนิพจน์ทั้งหมดใน parens ได้หากคุณเคลื่อนที่ไปมาระหว่าง go และ python เนื่องจากเทคนิคนี้ใช้ได้กับทั้งสองภาษา


เคล็ดลับดีๆเกี่ยวกับการออกจากตัวดำเนินการในตอนท้าย มันได้ผล
Karlom

1
การห่อในวงเล็บใช้ไม่ได้ใน go afaik ยังคงใส่อัฒภาคไว้ในวงเล็บ
Adrian Shum

ฉันเพิ่งลองใช้และ Go ใส่อัฒภาคที่มองไม่เห็นจริงๆแม้จะอยู่ในวงเล็บก็ตาม ดังนั้นสิ่งนี้ใช้ได้เฉพาะใน Python ไม่ใช่ใน Go
Roland Illig

@RolandIllig ใช้งานได้แน่นอน: play.golang.org/p/oFKaxLTphU
tobyodavies

ขออภัยสำหรับคำพูดของฉันฉันอ้างถึงการใช้วงเล็บ (แต่ไม่ได้เขียนว่า) การห่อนิพจน์ในวงเล็บอาจใช้ได้ใน Python แต่ใช้ไม่ได้ใน Go
Roland Illig

17

ดังที่กล่าวมานี้เป็นเรื่องของสไตล์ความชอบ ฉันเข้าใจว่าผู้สร้าง Go ได้แนะนำสไตล์จากประสบการณ์ของพวกเขาที่ฉันได้เรียนรู้มา แต่ยังเก็บสไตล์ของฉันเองจากประสบการณ์ของฉันด้วย

ด้านล่างนี้คือวิธีที่ฉันจะจัดรูปแบบสิ่งนี้:

err := database.
  QueryRow("select * from users where user_id=?", id).
  Scan(
    &ReadUser.ID,
    &ReadUser.Name,
    &ReadUser.First,
    &ReadUser.Last,
    &ReadUser.Email,
  )

16

มันเป็นเรื่องของสไตล์ แต่ฉันชอบ:

err := database.QueryRow(
    "select * from users where user_id=?", id,
).Scan(
    &ReadUser.ID, &ReadUser.Name, &ReadUser.First, &ReadUser.Last, &ReadUser.Email,
)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.