-
Notifications
You must be signed in to change notification settings - Fork 18.8k
Description
I intend to add the SHGetKnownFolderPath API to x/sys/windows, because it's the right way for looking up things like where an application should store its configuration or where various other standard folders are located. That's kind of boring. The function takes some constant enumeration parameter indicating which folder type to return. Usually in x/sys/windows for this, we import the symbolic names to make that easier. For example, for CreateWellKnownSid, we have something like this:
const (
WinNullSid = 0
WinWorldSid = 1
WinLocalSid = 2
WinCreatorOwnerSid = 3
WinCreatorGroupSid = 4
...
)And then users get to call CreateWellKnownSid(WinCreatorGroupSid) or something.
So far so good.
What's interesting is that the SHGetKnownFolderPath API is one that, rather than taking a numerical constant, takes a GUID constant. In C, this generally amounts to the Windows headers declaring a macro that expands to the curly braces defining the complex object, so you only have them in the resultant binary if you use them. In Go, it seems like it might be another story.
There are a few of these types of constant-GUID-taking APIs in x/sys/windows already, and they declare the "constant" GUID as a global variable. For example:
type GUID struct {
Data1 uint32
Data2 uint16
Data3 uint16
Data4 [8]byte
}
var WSAID_CONNECTEX = GUID{
0x25a207b9,
0xddf3,
0x4660,
[8]byte{0x8e, 0xe9, 0x76, 0xe5, 0x8c, 0x74, 0x06, 0x3e},
}
var WSAID_WSASENDMSG = GUID{
0xa441e712,
0x754f,
0x43ca,
[8]byte{0x84, 0xa7, 0x0d, 0xee, 0x44, 0xcf, 0x60, 0x6d},
}
var WSAID_WSARECVMSG = GUID{
0xf689d7c8,
0x6f1f,
0x436b,
[8]byte{0x8a, 0x53, 0xe5, 0x4f, 0xe3, 0x51, 0xc3, 0x22},
}Two things immediately leap out at me:
- Users of the library can modify the value of these at runtime; they're not read-only.
- These aren't actually constants, but runtime global variables that I assume are initialized at startup or if the compiler is smart held in some section of the binary.
This seems somewhat bad. Maybe the compiler optimizes (2) away if it's not used? But maybe it doesn't? Does anybody know? I sort of suspect it doesn't.
Getting back to the API I'd like to add, there are quite a few constant GUIDs that will be added as "constants". Due to (1) and (2) above, and the large quantity of these, it seems like declaring them as a var like that would be a really bad idea.
But I don't know of a language construct in Go that would actually fix this the right way, or whether the existing one is fine and the compiler does something smart with it. Does anybody know?