๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด/Go & Rust

[Go] Modern Go ๊ธฐ๋ณธ

by ์„œ์•„๋ž‘๐Ÿ˜ 2025. 5. 21.

 

๋“ค์–ด๊ฐ€๋ฉฐ

Go์˜ ๊ธฐ๋ณธ ์‚ฌ์šฉ๋ฒ•์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๊ธฐ์ดˆ ๋ฌธ๋ฒ•์— ๋Œ€ํ•ด์„œ ๋‹ค๋ฃจ์ง€๋Š” ์•Š์Šต๋‹ˆ๋‹ค. ํƒ€ ์–ธ์–ด์™€ ๋น„๊ตํ–ˆ์„ ๋•Œ ์–ด๋–ค ํŽธ๋ฆฌํ•œ ์ ๊ณผ ์ฐจ์ด๊ฐ€ ์žˆ๋Š”์ง€ ๊ฐ„๋‹จํžˆ ์งš์–ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

 

๋ณ€์ˆ˜

  • ์ •์ˆ˜ ํƒ€์ž…: int8/16/32/64, uint8/16/32/64, int, uint, rune
  • rune: UTF-8์ธ์ฝ”๋”ฉ์˜ ์œ ๋‹ˆ์ฝ”๋“œ ์ฝ”๋“œ ํฌ์ธํŠธ๋ฅผ ํ‘œ์‹œํ•˜๋Š” ์ •์ˆ˜
  • ๊ธฐ๋ณธ๊ฐ’: ์ •์ˆ˜ 0, ์‹ค์ˆ˜ 0.0, ๋ถˆ๋ฆฌ์–ธ false, ๋ฌธ์ž์—ด “”, ๊ทธ์™ธ nil
  • ์•”์‹œ์  ํƒ€์ž…๋ณ€ํ™˜ ํ—ˆ์šฉX
  • ์‹ค์ˆ˜ ๋น„๊ต์‹œ math.Nexafter๋กœ ๋น„๊ตํ•˜๋ฉด ํŽธ๋ฆฌ
  • a, b = b, a ์Šค์™‘
  • iota๋กœ ์—ด๊ฑฐ๊ฐ’ ์‚ฌ์šฉ
const (
  Red    int = iota  // 0
  Blue   int = iota  // 1
  Green  int = iota  // 2
  Yellow int = iota + 1  // 3 + 1 = 4
)
  • ๋„ค์ด๋ฐ ์ปจ๋ฒค์…˜
    • Go ์–ธ์–ด์—์„œ๋Š” ๋Œ€๋ฌธ์ž๋กœ ์‹œ์ž‘ํ•˜๋Š” ์‹๋ณ„์ž๋งŒ ์™ธ๋ถ€ ํŒจํ‚ค์ง€์—์„œ ์ ‘๊ทผ ๊ฐ€๋Šฅ

 

์กฐ๊ฑด๋ฌธ(if, switch)

  • if ์ดˆ๊ธฐ๋ฌธ; ์กฐ๊ฑด๋ฌธ
if filename, success := UploadFile(); success {
  ...
}
  • switch์— ๋“ค์–ด๊ฐ€๋Š” ์ธ์ž์—๋Š” ๋ฌธ์ž์—ด๋„ ํ—ˆ์šฉ(case “monday”:)
  • case์—์„œ break ๋ช…์‹œ ์•ˆํ•ด์ค˜๋„ ์•Œ์•„์„œ ๋จ
  • switch์— ์กฐ๊ฑด ๋น„๊ต๊ฐ€ ๋‹ค์–‘
switch true {   // true ์ƒ๋žต ๊ฐ€๋Šฅ
  case temp < 10, temp > 30:
    fmt.println("๋ฐ”๊นฅ ํ™œ๋™ํ•˜๊ธฐ ์ข‹์€ ๋‚ ์”จ๊ฐ€ ์•„๋‹˜")
  case humidity > 50:
	  fmt.println("์Šต๋„๊ฐ€ ๋„ˆ๋ฌด ๋†’์Œ")
}

switch age := getMyAge(); age {
  case 10:
    fmt.println("Teenage")
  ...

 

๋ฐ˜๋ณต๋ฌธ(for)

  • ์ง๊ด€์„ฑ์„ ์œ„ํ•ด while ์ง€์›ํ•˜์ง€ ์•Š์Œ
  • for { … } ๋Š” ๋ฌดํ•œ ๋ฃจํ”„(while true ๋Œ€์ฒด)
  • range ์‚ฌ์šฉ ๋ฐ˜๋ณต(์‚ฌ์šฉ ๋นˆ๋„ ๋†’์Œ)
nums := []int{10, 20, 30}
for i, v := range nums {
    fmt.Println(i, v)
}

m := map[string]int{"a": 1, "b": 2}
for k, v := range m {
    fmt.Println(k, v)
}

 

๊ตฌ์กฐ์ฒด

  • ํฌํ•จ๋œ ํ•„๋“œ(๊ตฌ์กฐ์ฒด ์•ˆ์— ํฌํ•จ๋œ ๋‹ค๋ฅธ ๊ตฌ์กฐ์ฒด์˜ ํ•„๋“œ๋ช… ์ƒ๋žต)
type User struct {
  Name string
  ID string
}

type VIPInfo struct {
  User       // ํ•„๋“œ๋ช… ์ƒ๋žต
  Level int
  Price int
}

vip := VIPInfo{ User{ "๋ฐ•์ง€์ƒ", "jisang"}, 3, 250 }
fmt.Printf("Name of VIP: %v", vip.Name) // ๊ตฌ์กฐ์ฒด ์•ˆ์— ํฌํ•จ๋œ ๋‹ค๋ฅธ ๊ตฌ์กฐ์ฒด์˜ ํ•„๋“œ๋ช… ์ƒ๋žต

 

ํฌ์ธํ„ฐ

  • ํฌ์ธํ„ฐ ์—ฐ์‚ฐ(+, -) ๋ถˆ๊ฐ€
  • ๊ธฐ๋ณธ์ ์œผ๋กœ GC ์ง€์›
  • new ์‚ฌ์šฉ
p1 := &Data{3, 4}   // Data ์ธ์Šคํ„ด์Šค ์ƒ์„ฑ ๋ฐ p1 ํฌ์ธํ„ฐ ์ฐธ์กฐ, ๋งค๊ฐœ๋ณ€์ˆ˜ ์ดˆ๊ธฐํ™” ๊ฐ€๋Šฅ
var p2 = new(Data)  // new ํ‚ค์›Œ๋“œ ์‚ฌ์šฉ, ๋งค๊ฐœ๋ณ€์ˆ˜ ์ดˆ๊ธฐํ™” ๋ถˆ๊ฐ€๋Šฅ

 

์šฉ์–ด ์„ค๋ช…
& ๋ณ€์ˆ˜์˜ ์ฃผ์†Œ๋ฅผ ๊ฐ€์ ธ์˜ด (address-of operator)
* ํฌ์ธํ„ฐ๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” ๊ฐ’์„ ์ฝ์Œ/๋ณ€๊ฒฝ (dereference operator)
*T ํƒ€์ž… T์— ๋Œ€ํ•œ ํฌ์ธํ„ฐ

 

ํŒจํ‚ค์ง€

  • fmt ํŒจํ‚ค์ง€(formatted I/O)
    • fmt::Print(), fmt::Println(), fmt::Printf()
    • ํ˜•์‹ ์ง€์ •์ž %v: ์ž๋™ ํƒ€์ž… ์ถ”๋ก , %T: ๋ฐ์ดํ„ฐ ํƒ€์ž… ์ถœ๋ ฅ, %t: ๋ถˆ๋ฆฌ์–ธ์„ true/false๋กœ ์ถœ๋ ฅ
  • ํŒจํ‚ค์ง€ ๋ณ„์นญ
import (
  "text/template"
  "html/template"  // ๊ฐ™์€ ์ด๋ฆ„์˜ ํŒจํ‚ค์ง€
 )
 
 
 import (
  "text/template"
  htemplate "html/template"  // ๋ณ„์นญ: htemplate
 )
 
template.New("foo").Parse(`{{define "T"}}Hello`)
htemplate.New("foo").Parse(`{{define "T"}}Hello`)
  • Go ๋ชจ๋“ˆ
    • Go ํŒจํ‚ค์ง€๋ฅผ ๋ชจ์•„๋†“์€ Go ํ”„๋กœ์ ํŠธ ๋‹จ์œ„
    • Go 1.16๋ฒ„์ „๋ถ€ํ„ฐ Go ๋ชจ๋“ˆ ์‚ฌ์šฉ์ด ๊ธฐ๋ณธ์ด ๋์Œ(๋ชจ๋“  Go ์ฝ”๋“œ๋Š” Go ๋ชจ๋“ˆ ์•„๋ž˜ ์žˆ์–ด์•ผ ํ•จ)
    • go.mod ํŒŒ์ผ์„ ํ†ตํ•ด Go ๋ฒ„์ „, ํ•„์š”ํ•œ ์™ธ๋ถ€ ํŒจํ‚ค์ง€ ๋ช…์‹œ
    • go mod init(์ดˆ๊ธฐํ™”), go mod tidy(ํŒจํ‚ค์ง€ ๋‹ค์šด๋กœ๋“œ)
    • go.sumํŒŒ์ผ: ํŒจํ‚ค์ง€ ์œ„์กฐ ์—ฌ๋ถ€๋ฅผ ๊ฒ€์‚ฌํ•˜๊ธฐ ์œ„ํ•œ ์ฒดํฌ์„ฌ(checksum) ๊ฒฐ๊ณผ
  • ํŒจํ‚ค์ง€ ์™ธ๋ถ€ ๊ณต๊ฐœ
    • ํŒจํ‚ค์ง€ ์ „์—ญ์œผ๋กœ ์„ ์–ธ๋œ ์ฒซ ๊ธ€์ž๊ฐ€ ๋Œ€๋ฌธ์ž๋กœ ์‹œ์ž‘๋˜๋Š” ๋ชจ๋“  ๋ณ€์ˆ˜, ์ƒ์ˆ˜, ํƒ€์ž…, ํ•จ์ˆ˜๋Š” ์™ธ๋ถ€๋กœ ๊ณต๊ฐœ
  • ํŒจํ‚ค์ง€ ์ดˆ๊ธฐํ™”
    • ํŒจํ‚ค์ง€๋ฅผ ์ž„ํฌํŠธํ•˜๋ฉด ์ปดํŒŒ์ผ๋Ÿฌ๋Š” ํŒจํ‚ค์ง€ ๋‚ด ์ „์—ญ๋ณ€์ˆ˜๋ฅผ ์ดˆ๊ธฐํ™” ํ•จ
    • ํŒจํ‚ค์ง€์— init() ํ•จ์ˆ˜๊ฐ€ ์žˆ๋‹ค๋ฉด ํ˜ธ์ถœํ•ด ํŒจํ‚ค์ง€๋ฅผ ์ดˆ๊ธฐํ™”
    • init()ํ•จ์ˆ˜๋Š” ๋ฐ˜๋“œ์‹œ ์ž…๋ ฅ ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ์—†๊ณ  ๋ฐ˜ํ™˜๊ฐ’๋„ ์—†๋Š” ํ•จ์ˆ˜์—ฌ์•ผ ํ•จ
๐Ÿ’ก ํŒจํ‚ค์ง€ A๊ฐ€ ๋‹ค๋ฅธ ํŒจํ‚ค์ง€ B๋ฅผ importํ•˜๋Š” ๊ฒฝ์šฐ:
ํŒจํ‚ค์ง€ B์˜ ์ „์—ญ ๋ณ€์ˆ˜ ์„ ์–ธ → init() ํ˜ธ์ถœ๊ทธ ๋‹ค์Œ์— ํŒจํ‚ค์ง€ A์˜ ์ „์—ญ ๋ณ€์ˆ˜ ์„ ์–ธ → init() ํ˜ธ์ถœ
์ฆ‰, ์˜์กด์„ฑ์ด ๊นŠ์€ ์ชฝ์ด ๋จผ์ € ์ดˆ๊ธฐํ™”๋จ.
// ์˜ˆ์‹œ

// a.go
package a

import "fmt"

var A = initA()

func initA() int {
    fmt.Println("a.go: ์ „์—ญ ๋ณ€์ˆ˜ A ์ดˆ๊ธฐํ™”")
    return 1
}

func init() {
    fmt.Println("a.go: init ํ•จ์ˆ˜ ํ˜ธ์ถœ")
}
// main.go
package main

import (
    "fmt"
    _ "yourmodule/a" // ๊ฐ•์ œ import (init ์‹คํ–‰๋งŒ ์›ํ•  ๋•Œ)(๋ฐ‘์ค„ _์„ ์ด์šฉํ•ด์„œ init() ํ•จ์ˆ˜๋งŒ ํ˜ธ์ถœ)
)

func main() {
    fmt.Println("main ์‹คํ–‰")
}
a.go: ์ „์—ญ ๋ณ€์ˆ˜ A ์ดˆ๊ธฐํ™”
a.go: init ํ•จ์ˆ˜ ํ˜ธ์ถœ
main ์‹คํ–‰

 

๋ฌธ์ž์—ด

  • ๊ธฐ๋ณธ
    • ๋ฌธ์ž์—ด์€ ๊ธฐ๋ณธ์ ์œผ๋กœ ๋ถˆ๋ณ€ → ๋ฌธ์ž์—ด์€ ๋ถˆ๋ณ€์ด๊ณ  ๊ฐ’ ํƒ€์ž…์ด๋ฏ€๋กœ ํ•จ์ˆ˜ ์ธ์ž๋กœ ๋„˜๊ธฐ๋ฉด ๋ณต์‚ฌ๋จ
  • ๋ฌธ์ž์—ด ์ˆœํšŒ
// byte ๋‹จ์œ„ ์ˆœํšŒ
for i := 0; i < len(s); i++ {
    fmt.Printf("%c ", s[i])  // ํ•œ๊ธ€ ๋“ฑ ์œ ๋‹ˆ์ฝ”๋“œ ๊นจ์ง
}

// rune ๋‹จ์œ„ ์ˆœํšŒ(์ •์ƒ ํ•œ๊ธ€์ฒ˜๋ฆฌ)
for i, r := range s {
    fmt.Printf("index: %d, rune: %c\\n", i, r)
}
  • ๋ฌธ์ž์—ด ์ฃผ์š” ํ•จ์ˆ˜(strings ํŒจํ‚ค๊ธฐ)
import "strings"

strings.HasPrefix(s, "pre")   // ์ ‘๋‘์‚ฌ ํ™•์ธ
strings.HasSuffix(s, "fix")   // ์ ‘๋ฏธ์‚ฌ ํ™•์ธ
strings.Contains(s, "lo")     // ํฌํ•จ ์—ฌ๋ถ€
strings.ToUpper(s)            // ๋Œ€๋ฌธ์ž ๋ณ€ํ™˜
strings.ToLower(s)            // ์†Œ๋ฌธ์ž ๋ณ€ํ™˜
strings.TrimSpace(s)          // ๊ณต๋ฐฑ ์ œ๊ฑฐ
strings.Split(s, ",")         // ๋ฌธ์ž์—ด ๋ถ„ํ• 
strings.Join([]string{"a", "b"}, "-") // "a-b"

 

๋Œ“๊ธ€