해야지해야지 하다가 어느덧 시간이 훅 지나버린 1.22.0 Release 정리글 되시겠다. (Release note)

For loop
- for loop내부의 변수는 한번 선언된 후 재사용 했었으나, 1.22에서는 매번 선언되도록 변경되었다.
- 새로운 range를 제공한다.
이 개선들을 통해 아래의 두 로직은 같은 동작을 한다.
// go 1.21
func main() {
var wg sync.WaitGroup
for _, val := range []int{0, 1, 2, 3, 4} {
wg.Add(1)
go func(v int, pWG *sync.WaitGroup) {
defer pWG.Done()
fmt.Printf("%d ", v)
}(val, &wg)
}
wg.Wait()
}
//////////////////////////////////////////////////////////////////////////////////////////////
// go 1.22
func main() {
var wg sync.WaitGroup
for val := range 5 {
wg.Add(1)
go func(pWG *sync.WaitGroup) {
defer pWG.Done()
fmt.Printf("%d ", val)
}(&wg)
}
wg.Wait()
}
math/rand/v2 추가
기존 math/rand package의 Read(p []byte) (n int, err error)가 Deprecated되었다.
- len(p)의 랜덤 byte를 할당하는 함수로 아래와 같은 기능을 제공했었다.
randomBytes := make([]byte, 32)
fmt.Println(randomBytes) // 모두 0
rand.Read(randomBytes)
fmt.Println(randomBytes) // 0~255사이의 랜덤값이 들어간다.
- Deprecated된 이유를 따로 설명해주진 않았다. 하지만 해당 내용에서 언급한 The vast majority of calls to Read should use crypto/rand’s Read instead.란 말로 미루어 보아 rand.Read()를 사용하여 Key를 생성하는 경우를 막기 위함으로 생각된다.
- rand.Read()는 time.Now().UnixNano()를 기반으로 하는 난수값을 생성한다. 즉, 예측 가능하다는 의미인데 이를 사용해서 key값을 생성해서 사용하면 보안에 문제가 될 수 있다.
Top-Level의 함수명이 변경되었다.
- Intn, Int31, Int31n, Int63, Int63n → IntN, Int32, Int32N, Int64, Int64N.
- 각각 31bit와 63bit integer를 return하지만, 정적 반환되는 type명은 int32와 int64었는데 통일되었다.
Unsigned 함수들이 추가되었다
- Uint32, Uint32N, Uint64, Uint64N, Uint, UintN.
Generic N함수가 추가되었다.
- unsigned를 포함한 모든 integer type과, duration까지 지원한다.
{
// random integer
var max int32 = 100
n := rand.N(max)
fmt.Println("integer n =", n)
}
{
// random unsigned integer
var max uint64 = 100
n := rand.N(max)
fmt.Println("unsigned int n =", n)
}
{
// random duration
var max time.Duration = 100 * time.Millisecond
n := rand.N(max)
fmt.Println("duration n =", n)
}
go/version package 추가
Go version에 관련된 package가 추가되었다.
version의 확인, 비교, Validation check를 지원한다.
v := runtime.Version()
fmt.Println(version.IsValid(v)) //true
fmt.Println(version.Lang(v)) // go1.22
fmt.Println(version.Compare(v, "go1.21rc2")) // 1
fmt.Println(version.Compare("go1.21rc2", v)) // -1
slices
Concat이 추가되었다.
s1 := []int{1, 2}
s2 := []int{3, 4}
s3 := []int{5, 6}
res := slices.Concat(s1, s2, s3)
fmt.Println(res) // {1, 2, 3, 4, 5, 6}
Delete, DeleteFunc, Compact, CompactFunc, Replace사용 시 src값의 길이가 변경되지 않고, 0이 할당되도록 변경되었다.
- 이는 길이 변경 시 copy를 사용하여 element를 이동 시키는데 이 과정에서 잘려진 값들이 gc되지 못하여 Memory leak이 발생하고 있어 수정되었다. (#63393)
src := []int{11, 12, 13, 14}
// delete #1 and #2
mod := slices.Delete(src, 1, 3)
fmt.Println("src:", src)
// 1.21: 11, 12
// 여기서 2,3번 index의 값이 reference type인 경우 gc되지 않고 남는다.
// 1.22: 11, 14, 0, 0
fmt.Println("mod:", mod)
// 1.21: 11, 14
// 1.22: 11, 14
Routing pattern
GET /items/{id}
- GET method만 한정하여 URL상에서 {id}와 같은 Segment가 매칭되어 Request value로 사용할 수 있다.
- posts/{id}와 posts/latest와 같이 만약 두 API가 겹치는 경우는 most specific wins에 따라 매칭된다. posts/latest로 호출되면 경우는 후자가, posts/text가 호출 되면 전자가 호출 될 것이다.
/file/{path…}
- 패턴의 마지막에 ...이 위치하는 경우 /file/*path와 같이 동작하게 된다.
/exact/match/{$}
- 마지막이 /나 {$}로 끝나는 경우 모든 prefix를 가진 모든 url path와 매칭된다.
encoding/json
-
\u0008이 \b로, \u000c가 \f로 encoding된다.
func fixJSON(data []byte) []byte {
data = bytes.Replace(data, []byte("\\u003c"), []byte("<"), -1)
data = bytes.Replace(data, []byte("\\u003e"), []byte(">"), -1)
data = bytes.Replace(data, []byte("\\u0026"), []byte("&"), -1)
data = bytes.Replace(data, []byte("\\u0008"), []byte("\\b"), -1)
data = bytes.Replace(data, []byte("\\u000c"), []byte("\\f"), -1)
return data
}
참고
'Golang' 카테고리의 다른 글
CGO를 사용하여 Golang과 CPP간 배열을 주고받는 방법 (0) | 2024.04.10 |
---|---|
Go를 3년간 사용하면서 느낀 개인적인 장단점 (0) | 2024.04.09 |
Go GC의 Memory overhead와 비용 (0) | 2024.04.09 |
[Golang] Go GC(Gargbae Collection)에 대해 (1) | 2024.04.07 |