diff --git a/doc/effective_go.html b/doc/effective_go.html index becfd17b2a..bdea687f1f 100644 --- a/doc/effective_go.html +++ b/doc/effective_go.html @@ -618,31 +618,112 @@ func Compare(a, b []byte) int { } +

Functions

+ +

Multiple return values

+ +

+One of Go's unusual properties is that functions and methods +can return multiple values. This feature can be used to +improve on a couple of clumsy idioms in C program: in-band +error returns (-1 for EOF for example) +and modifying an argument. +

+ +

+In C, a write error is signaled by a negative byte count with the +error code secreted away in a volatile location. +In Go, Write +can return a byte count and an error: "Yes, you wrote some +bytes but not all of them because you filled the device". +The signature of *File.Write in package os is: +

+ +
+func (file *File) Write(b []byte) (n int, err Error)
+
+ +

+and as the documentation says, it returns the number of bytes +written and a non-nil Error when n +!= len(b). +This is a common style; see the section on error handling for more examples. +

+ +

+A similar approach obviates the need to pass a pointer to a return +value to overwrite an argument. Here's a simple-minded function to +grab a number from a position in a byte array, returning the number +and the next position. +

+ +
+func nextInt(b []byte, i int) (int, int) {
+	for ; i < len(b) && !isDigit(b[i]); i++ {
+	}
+	x := 0;
+	for ; i < len(b) && isDigit(b[i]); i++ {
+		x = x*10 + int(b[i])-'0'
+	}
+	return x, i;
+}
+
+ +

+You could use it to scan the numbers in an input array a like this: +

+ +
+	for i := 0; i < len(a); {
+		x, i = nextInt(a, i);
+		fmt.Println(x);
+	}
+
+ +

Named result parameters

+ +

+The return or result "parameters" of a Go function can be given names and +used as regular variables, just like the incoming parameters. +When named, they are initialized to the zero for their type when +the function begins; if the function executes a return statement +with no arguments, the current values of the result parameters are +used as the returned values. +

+ +

+The names are not mandatory but they can make code shorter and clearer: +they're documentation. +If we name the results of nextInt it becomes +obvious which returned int +is which. +

+ +
+func nextInt(b []byte, pos int) (value, nextPos int) {
+
+ +

+Because named results are initialized and tied to an unadorned return, they can simplify +as well as clarify. Here's a version +of io.ReadFull that uses them well: +

+ +
+func ReadFull(r Reader, buf []byte) (n int, err os.Error) {
+	for len(buf) > 0 && err != nil {
+		var nr int;
+		nr, err = r.Read(buf);
+		n += nr;
+		buf = buf[nr:len(buf)];
+	}
+	return;
+}
+
+

More to come