From 6f89f3f08dc0aa6b2bfb323e09b1459784e87db9 Mon Sep 17 00:00:00 2001 From: Rob Pike Date: Tue, 20 Oct 2009 17:32:16 -0700 Subject: [PATCH] initialization R=rsc DELTA=292 (124 added, 165 deleted, 3 changed) OCL=35936 CL=35939 --- doc/effective_go.html | 309 ++++++++++++++++++------------------------ 1 file changed, 134 insertions(+), 175 deletions(-) diff --git a/doc/effective_go.html b/doc/effective_go.html index 23eaf3ce783..0fad624263b 100644 --- a/doc/effective_go.html +++ b/doc/effective_go.html @@ -125,7 +125,7 @@ x<<8 + y<<16 -

Commentary

+

Commentary

Go provides C-style /* */ block comments @@ -1304,7 +1304,129 @@ There's even more to printing than we've covered here. See the godocfmt for the details.

-

Methods

+

Initialization

+ +

+Although it doesn't look superficially very different from +initialization in C or C++, initialization in Go is more powerful. +Complex structures can be built during initialization and the ordering +issues between initialized objects in different packages are handled +correctly. +

+ +

Constants

+ +

+Constants in Go are just that—constant. +They are created at compile time, even when defined as +locals in functions, +and can only be numbers, strings or booleans. +Because of the compile-time restriction, the expressions +that define them must be constant expressions, +evaluatable by the compiler. For instance, +1<<3 is a constant expression, while +math.Sin(math.Pi/4) is not because +the function call to math.Sin needs +to happen at run time. +

+ +

+In Go, enumerated constants are created using the iota +enumerator. Since iota can be part of an expression and +expressions can be implicitly repeated, it is easy to build intricate +sets of values. +

+

+type ByteSize float64
+const (
+	_ = iota;	// ignore first value by assigning to blank identifier
+	KB ByteSize = 1<<(10*iota);
+	MB;
+	GB;
+	TB;
+	PB;
+	YB;
+)
+
+

+The ability to attach a method such as String to a +type makes it possible for such values to format themselves +automatically for printing, even as part of a general type. +

+
+func (b ByteSize) String() string {
+	switch {
+	case s >= YB:
+		return fmt.Sprintf("%.2fYB", b/YB)
+	case s >= PB:
+		return fmt.Sprintf("%.2fPB", b/PB)
+	case s >= TB:
+		return fmt.Sprintf("%.2fTB", b/TB)
+	case s >= GB:
+		return fmt.Sprintf("%.2fGB", b/GB)
+	case s >= MB:
+		return fmt.Sprintf("%.2fMB", b/MB)
+	case s >= KB:
+		return fmt.Sprintf("%.2fKB", b/KB)
+	}
+	return fmt.Sprintf("%.2fB", b);
+}
+
+

+The expression YB prints as 1.00YB, +while ByteSize(1e13) prints as 9.09TB, +

+ +

Variables

+ +

+Variables can be initialized just like constants but the +initializer can be a general expression computed at run time. +

+
+var (
+	HOME = os.Getenv("HOME");
+	USER = os.Getenv("USER");
+	GOROOT = os.Getenv("GOROOT");
+)
+
+ +

The init function

+ +

+Finally, each source file can define its own init() function to +set up whatever state is required. The only restriction is that, although +goroutines can be launched during initialization, they will not begin +execution until it completes; initialization always runs as a single thread +of execution. +And finally means finally: init() is called after all the +variable declarations in the package have evaluated their initializers, +and those are evaluated only after all the imported packages have been +initialized. +

+

+Besides initializations that cannot be expressed as declarations, +a common use of init() functions is to verify or repair +correctness of the program state before real execution begins. +

+ +
+func init() {
+	if USER == "" {
+		log.Exit("$USER not set")
+	}
+	if HOME == "" {
+		HOME = "/usr/" + USER
+	}
+	if GOROOT == "" {
+		GOROOT = HOME + "/go"
+	}
+	// GOROOT may be overridden by --goroot flag on command line.
+	flag.StringVar(&GOROOT, "goroot", GOROOT, "Go root directory");
+}
+
+ +

Methods

Pointers vs. Values

@@ -2000,178 +2122,15 @@ for try := 0; try < 2; try++ { } -

More to come

- - +