현재 3권의 신간들인 Go Optimizations 101, Go Details & Tips 101Go Generics 101이 출간되어 있습니다. Leanpub 서점에서 번들을 모두 구입하시는 방법이 비용 대비 효율이 가장 좋습니다.

Go에 대한 많은 정보들과 Go 101 책들의 최신 소식을 얻으시려면 Go 101 트위터 계정인 @Go100and1을 팔로잉 해주세요.

It Is a Pity That Byte Elements of Go Constant Strings Are Not Constants. And It Is a Luck

Does the following Go program compile okay?

package main

const S = "Go"

const G = S[0]

func main() {}

Many gophers might think it should compile okay. But it fails to compile. Because element values of a string are always non-constant in Go, even if the string is a constant.

It is a pity that Go 1.0 didn't specify that elements of constant strings are also constants.

For backward-compatibility, the pity is hard to make up. For example, currently, the following program compiles okay. It prints 185 (-71 + 256).

package main

const S = "Go" // S[0] == 71

func main() {
	println(-S[0])
}

But if elements of constant strings become into constants, then the program will not compile, because the type of -S[0] is byte (aka. uint8), whereas -71 owerflows the range of byte.

It is a pity, it is also a luck.

If elements of constant strings are constants, then there will be parsing ambiguities in Go custom generic age. Since Go 1.18, the following line will be treated as generic type declaration, in which S is a type parameter and [4]*int is its constraint.

type T [S [4]*int] struct{}

However, if elements of constant strings are constants, then S [4] may be treated as constant byte value if S is a constant string. In the parsing phase, the compiler doesn't know what the identifier int denotes. A type or an integer constant? If it denotes an integer constant, and S [4] may be treated as constant byte value, then the above line is a valid ordinary array type declaration.

Luckily, now, Go compiler knows S [4] will never be constant, so it always tries to think the above line is not an ordinary array type declaration. No ambiguities happen here. Were elements of constant strings constants, the simplified type parameter declaration syntax couldn't be possible.

There is a proposal to let Go support constant arrays (and other constant composite values). However, the Go custom syntax design has almost sentenced that proposal to death. Because, similarly, the following code will lead to parsing ambiguities if array values may be declared as constants.

const A = [2]int{1, 2}
type BoolArray [A [1] * int]bool

To avoid absolutely sentencing the constant array proposal to death, elements of constant array must not be treated as constants, just as elements of constant strings are not treated as constants.

BTW, substrings are also never constants

The following code line doesn't compile in Go:

const _ = "Google"[:2]

Instead, the following line compiles:

var _ = "Google"[:2]

By this fact, the following program will print 128 0 (the reason is explained here).

package main

const S = "Go"

var a byte = 64 << len(S) / 2
var b byte = 64 << len(S[:]) / 2

func main() {
	println(a, b) // 128 0
}

So making substrings of constant strings constant will also break backward-compatibility.


Index↡

The Go 101 프로젝트는 Github 에서 호스팅됩니다. 오타, 문법 오류, 부정확한 표현, 설명 결함, 코드 버그, 끊어진 링크와 같은 모든 종류의 실수에 대한 수정 사항을 제출하여 Go 101을 개선을 돕는 것은 언제나 환영합니다.

주기적으로 Go에 대한 깊이 있는 정보를 얻고 싶다면 Go 101의 공식 트위터 계정인 @go100and1을 팔로우하거나 Go 101 슬랙 채널에j가입해주세요.

Go 101의 저자인 Tapir는 2016년 7월부터 Go 101 시리즈 책들을 집필하고 go101.org 웹사이트를 유지 관리하고 있습니다. 새로운 콘텐츠는 책과 웹사이트에 수시로 추가될 예정입니다. Tapir는 인디 게임 개발자이기도 합니다. Tapir의 게임을 플레이하여 Go 101을 지원할 수도 있습니다. (안드로이드와 아이폰/아이패드용):
  • Color Infection (★★★★★), 140개 이상의 단계로 이루어진 물리 기반의 캐주얼 퍼즐 게임
  • Rectangle Pushers (★★★★★), 2가지 모드와 104개 이상의 단계로 이루어진 캐주얼 퍼즐 게임
  • Let's Play With Particles, 세가지 미니 게임이 있는 캐주얼 액션 게임
페이팔을 통한 개인 기부도 환영합니다.

색인: