dev-resources.site
for different kinds of informations.
Compile-Time Assertions in Go (Golang)
A compile-time assertion is a mechanism used to enforce certain conditions or constraints at compile time rather than at runtime. If the condition is not met, the compilation process fails, and an error is generated. This is particularly useful for catching errors early in the development process, ensuring that certain invariants or assumptions hold true before the program is even executed.
Compile-time assertions are often used to:
- Ensure the size of a data structure is as expected.
- Verify that certain constants or expressions evaluate to specific values.
- Enforce type constraints or other compile-time checks.
Compile-Time Assertions in Go
Go does not have built-in support for compile-time assertions like some other languages. However, you can achieve similar functionality using creative techniques. Below are some common approaches.
Assert a constant boolean expression is true (or false) at compile time:
We could make use of the fact introduced in the following:
Go specification clearly specifies that the constant keys in a map/slice/array composite literal must not be duplicate.
For example, the following code assures that the constant boolean expression aBoolConst
must be true.
If it is not true, then the code fails to compile.
const aBoolConst = true
var _ = map[bool]int{false: 0, aBoolConst: 1}
Assert the length of a constant string is 15:
const STR = "abcdefghij12345"
var _ = map[bool]int{false: 0, len(STR) == 15: 1}
Assert a constant integer is 15:
var _ = [1]int{len(STR)-15: 0}
//OR
var _ = [1]int{}[len(STR)-15]
Assert a constant X
is not smaller than another constant Y
at compile time:
const _ uint = X-Y
//OR
type _ [X-Y]int
Assert a constant string is not blank:
var _ = aStringConst[0]
//OR
const _ = 1/len(aStringConst)
Using array size checks:
import "unsafe"
type MyStruct struct {
A int64
B int64
}
// Ensure the size of a struct is 16 bytes
var _ = [1]int{unsafe.Sizeof(MyStruct{}) - 16: 0}
Assert enum length:
type enumType int
const (
EnumA enumType = iota
EnumB
EnumC
end
)
var enumDescriptions = [...]string {
EnumA: "first",
EnumB: "second",
EnumC: "third",
}
func (e enumType) String() string {
if e < 0 || e >= end {
panic("invalid value")
}
return enumDescriptions[e]
}
var _ = [1]int{}[len(enumDescriptions) - int(end)]
func _() {
var x [1]struct{}
_ = x[EnumA - 0]
_ = x[EnumB - 1]
_ = x[EnumC - 2]
}
Using init
function with panic
:
While not strictly a compile-time assertion, you can use the init
function to perform checks that will fail at program startup (effectively acting as a runtime assertion during initialization):
const ExpectedSize = 8
var myInt int64
func init() {
if unsafe.Sizeof(myInt) != ExpectedSize {
panic("int size is not 8 bytes")
}
}
Featured ones: