From 5fea39d0b4091a75d76909334f532d341ce47b75 Mon Sep 17 00:00:00 2001 From: Andrew Gerrand Date: Wed, 29 Feb 2012 13:23:07 +1100 Subject: [PATCH] doc: remove Go for C++ Programmers Now available at the Go Wiki: http://code.google.com/p/go-wiki/wiki/GoForCPPProgrammers Fixes #2913. R=golang-dev, r CC=golang-dev https://golang.org/cl/5705049 --- doc/docs.html | 1 - doc/go_for_cpp_programmers.html | 807 -------------------------------- 2 files changed, 808 deletions(-) delete mode 100644 doc/go_for_cpp_programmers.html diff --git a/doc/docs.html b/doc/docs.html index 171c5cabf56..ccffad8a188 100644 --- a/doc/docs.html +++ b/doc/docs.html @@ -60,7 +60,6 @@ Answers to common questions about Go.

Go Articles

diff --git a/doc/go_for_cpp_programmers.html b/doc/go_for_cpp_programmers.html deleted file mode 100644 index f79f8cb3f8b..00000000000 --- a/doc/go_for_cpp_programmers.html +++ /dev/null @@ -1,807 +0,0 @@ - - -

-Go is a systems programming language intended to be a general-purpose -systems language, like C++. -These are some notes on Go for experienced C++ programmers. This -document discusses the differences between Go and C++, and says little -to nothing about the similarities. -

- -

-For a more general introduction to Go, see the -Go Tour, -How to Write Go Code -and Effective Go. -

- -

-For a detailed description of the Go language, see the -Go spec. -

- -

Conceptual Differences

- - - -

Syntax

- -

-The declaration syntax is reversed compared to C++. You write the name -followed by the type. Unlike in C++, the syntax for a type does not match -the way in which the variable is used. Type declarations may be read -easily from left to right. -

- -
-Go                           C++
-var v1 int                // int v1;
-var v2 string             // const std::string v2;  (approximately)
-var v3 [10]int            // int v3[10];
-var v4 []int              // int* v4;  (approximately)
-var v5 struct { f int }   // struct { int f; } v5;
-var v6 *int               // int* v6;  (but no pointer arithmetic)
-var v7 map[string]int     // unordered_map<string, int>* v7;  (approximately)
-var v8 func(a int) int    // int (*v8)(int a);
-
- -

-Declarations generally take the form of a keyword followed by the name -of the object being declared. The keyword is one of var, -func, -const, or type. Method declarations are a minor -exception in that -the receiver appears before the name of the object being declared; see -the discussion of interfaces. -

- -

-You can also use a keyword followed by a series of declarations in -parentheses. -

- -
-var (
-    i int
-    m float64
-)
-
- -

-When declaring a function, you must either provide a name for each parameter -or not provide a name for any parameter; you can't omit some names -and provide others. You may group several names with the same type: -

- -
-func f(i, j, k int, s, t string)
-
- -

-A variable may be initialized when it is declared. When this is done, -specifying the type is permitted but not required. When the type is -not specified, the type of the variable is the type of the -initialization expression. -

- -
-var v = *p
-
- -

-See also the discussion of constants, below. -If a variable is not initialized explicitly, the type must be specified. -In that case it will be -implicitly initialized to the type's zero value -(0, nil, etc.). There are no -uninitialized variables in Go. -

- -

-Within a function, a short declaration syntax is available with -:= . -

- -
-v1 := v2
-
- -

-This is equivalent to -

- -
-var v1 = v2
-
- -

-Go permits multiple assignments, which are done in parallel. -

- -
-i, j = j, i    // Swap i and j.
-
- -

-Functions may have multiple return values, indicated by a list in -parentheses. The returned values can be stored by assignment -to a list of variables. -

- -
-func f() (i int, j int) { ... }
-v1, v2 = f()
-
- -

-Go code uses very few semicolons in practice. Technically, all Go -statements are terminated by a semicolon. However, Go treats the end -of a non-blank line as a semicolon unless the line is clearly -incomplete (the exact rules are -in the language specification). -A consequence of this is that in some cases Go does not permit you to -use a line break. For example, you may not write -

-
-func g()
-{                  // INVALID
-}
-
-

-A semicolon will be inserted after g(), causing it to be -a function declaration rather than a function definition. Similarly, -you may not write -

-
-if x {
-}
-else {             // INVALID
-}
-
-

-A semicolon will be inserted after the } preceding -the else, causing a syntax error. -

- -

-Since semicolons do end statements, you may continue using them as in -C++. However, that is not the recommended style. Idiomatic Go code -omits unnecessary semicolons, which in practice is all of them other -than the initial for loop clause and cases where you want several -short statements on a single line. -

- -

-While we're on the topic, we recommend that rather than worry about -semicolons and brace placement, you format your code with -the gofmt program. That will produce a single standard -Go style, and let you worry about your code rather than your -formatting. While the style may initially seem odd, it is as good as -any other style, and familiarity will lead to comfort. -

- -

-When using a pointer to a struct, you use . instead -of ->. -Thus syntactically speaking a structure and a pointer to a structure -are used in the same way. -

- -
-type myStruct struct { i int }
-var v9 myStruct              // v9 has structure type
-var p9 *myStruct             // p9 is a pointer to a structure
-f(v9.i, p9.i)
-
- -

-Go does not require parentheses around the condition of an if -statement, or the expressions of a for statement, or the value of a -switch statement. On the other hand, it does require curly braces -around the body of an if or for statement. -

- -
-if a < b { f() }             // Valid
-if (a < b) { f() }           // Valid (condition is a parenthesized expression)
-if (a < b) f()               // INVALID
-for i = 0; i < 10; i++ {}    // Valid
-for (i = 0; i < 10; i++) {}  // INVALID
-
- -

-Go does not have a while statement nor does it have a -do/while -statement. The for statement may be used with a single condition, -which makes it equivalent to a while statement. Omitting the -condition entirely is an endless loop. -

- -

-Go permits break and continue to specify a label. -The label must -refer to a for, switch, or select -statement. -

- -

-In a switch statement, case labels do not fall -through. You can -make them fall through using the fallthrough keyword. This applies -even to adjacent cases. -

- -
-switch i {
-case 0:  // empty case body
-case 1:
-    f()  // f is not called when i == 0!
-}
-
- -

-But a case can have multiple values. -

- -
-switch i {
-case 0, 1:
-    f()  // f is called if i == 0 || i == 1.
-}
-
- -

-The values in a case need not be constants—or even integers; -any type -that supports the equality comparison operator, such as strings or -pointers, can be used—and if the switch -value is omitted it defaults to true. -

- -
-switch {
-case i < 0:
-    f1()
-case i == 0:
-    f2()
-case i > 0:
-    f3()
-}
-
- -

-The ++ and -- operators may only be used in -statements, not in expressions. -You cannot write c = *p++. *p++ is parsed as -(*p)++. -

- -

-The defer statement may be used to call a function after -the function containing the defer statement returns. -

- -
-fd := open("filename")
-defer close(fd)         // fd will be closed when this function returns.
-
- -

Constants

- -

-In Go constants may be untyped. This applies even to constants -named with a const declaration, if no -type is given in the declaration and the initializer expression uses only -untyped constants. -A value derived from an untyped constant becomes typed when it -is used within a context that -requires a typed value. This permits constants to be used relatively -freely without requiring general implicit type conversion. -

- -
-var a uint
-f(a + 1)  // untyped numeric constant "1" becomes typed as uint
-
- -

-The language does not impose any limits on the size of an untyped -numeric constant or constant expression. A limit is only applied when -a constant is used where a type is required. -

- -
-const huge = 1 << 100
-f(huge >> 98)
-
- -

-Go does not support enums. Instead, you can use the special name -iota in a single const declaration to get a -series of increasing -value. When an initialization expression is omitted for a const, -it reuses the preceding expression. -

- -
-const (
-    red = iota   // red == 0
-    blue         // blue == 1
-    green        // green == 2
-)
-
- -

Slices

- -

-A slice is conceptually a struct with three fields: a -pointer to an array, a length, and a capacity. -Slices support -the [] operator to access elements of the underlying array. -The builtin -len function returns the -length of the slice. The builtin cap function returns the -capacity. -

- -

-Given an array, or another slice, a new slice is created via -a[i:j]. This -creates a new slice which refers to a, starts at -index i, and ends before index -j. It has length j-i. -If i is omitted, the slice starts at 0. -If j is omitted, the slice ends at len(a). -The new slice refers to the same array -to which a -refers. That is, changes made using the new slice may be seen using -a. The -capacity of the new slice is simply the capacity of a minus -i. The capacity -of an array is the length of the array. -

- -

-What this means is that Go uses slices for some cases where C++ uses pointers. -If you create a value of type [100]byte (an array of 100 bytes, -perhaps a -buffer) and you want to pass it to a function without copying it, you should -declare the function parameter to have type []byte, and -pass a slice of the array (a[:] will pass the entire array). -Unlike in C++, it is not -necessary to pass the length of the buffer; it is efficiently accessible via -len. -

- -

-The slice syntax may also be used with a string. It returns a new string, -whose value is a substring of the original string. -Because strings are immutable, string slices can be implemented -without allocating new storage for the slices's contents. -

- -

Making values

- -

-Go has a builtin function new which takes a type and -allocates space -on the heap. The allocated space will be zero-initialized for the type. -For example, new(int) allocates a new int on the heap, -initializes it with the value 0, -and returns its address, which has type *int. -Unlike in C++, new is a function, not an operator; -new int is a syntax error. -

- -

-Perhaps surprisingly, new is not commonly used in Go -programs. In Go taking the address of a variable is always safe and -never yields a dangling pointer. If the program takes the address of -a variable, it will be allocated on the heap if necessary. So these -functions are equivalent: -

- -
-type S { I int }
-
-func f1() *S {
-	return new(S)
-}
-
-func f2() *S {
-	var s S
-	return &s
-}
-
-func f3() *S {
-	// More idiomatic: use composite literal syntax.
-	return &S{0}
-}
-
- -

-Map and channel values must be allocated using the builtin function -make. -A variable declared with map or channel type without an initializer will be -automatically initialized to nil. -Calling make(map[int]int) returns a newly allocated value of -type map[int]int. -Note that make returns a value, not a pointer. This is -consistent with -the fact that map and channel values are passed by reference. Calling -make with -a map type takes an optional argument which is the expected capacity of the -map. Calling make with a channel type takes an optional -argument which sets the -buffering capacity of the channel; the default is 0 (unbuffered). -

- -

-The make function may also be used to allocate a slice. -In this case it -allocates memory for the underlying array and returns a slice referring to it. -There is one required argument, which is the number of elements in the slice. -A second, optional, argument is the capacity of the slice. For example, -make([]int, 10, 20). This is identical to -new([20]int)[0:10]. Since -Go uses garbage collection, the newly allocated array will be discarded -sometime after there are no references to the returned slice. -

- -

Interfaces

- -

-Where C++ provides classes, subclasses and templates, -Go provides interfaces. A -Go interface is similar to a C++ pure abstract class: a class with no -data members, with methods which are all pure virtual. However, in -Go, any type which provides the methods named in the interface may be -treated as an implementation of the interface. No explicitly declared -inheritance is required. The implementation of the interface is -entirely separate from the interface itself. -

- -

-A method looks like an ordinary function definition, except that it -has a receiver. The receiver is similar to -the this pointer in a C++ class method. -

- -
-type myType struct { i int }
-func (p *myType) Get() int { return p.i }
-
- -

-This declares a method Get associated with myType. -The receiver is named p in the body of the function. -

- -

-Methods are defined on named types. If you convert the value -to a different type, the new value will have the methods of the new type, -not the old type. -

- -

-You may define methods on a builtin type by declaring a new named type -derived from it. The new type is distinct from the builtin type. -

- -
-type myInteger int
-func (p myInteger) Get() int { return int(p) } // Conversion required.
-func f(i int) { }
-var v myInteger
-// f(v) is invalid.
-// f(int(v)) is valid; int(v) has no defined methods.
-
- -

-Given this interface: -

- -
-type myInterface interface {
-	Get() int
-	Set(i int)
-}
-
- -

-we can make myType satisfy the interface by adding -

- -
-func (p *myType) Set(i int) { p.i = i }
-
- -

-Now any function which takes myInterface as a parameter -will accept a -variable of type *myType. -

- -
-func GetAndSet(x myInterface) {}
-func f1() {
-	var p myType
-	GetAndSet(&p)
-}
-
- -

-In other words, if we view myInterface as a C++ pure abstract -base -class, defining Set and Get for -*myType made *myType automatically -inherit from myInterface. A type may satisfy multiple interfaces. -

- -

-An anonymous field may be used to implement something much like a C++ child -class. -

- -
-type myChildType struct { myType; j int }
-func (p *myChildType) Get() int { p.j++; return p.myType.Get() }
-
- -

-This effectively implements myChildType as a child of -myType. -

- -
-func f2() {
-	var p myChildType
-	GetAndSet(&p)
-}
-
- -

-The set method is effectively inherited from -myType, because -methods associated with the anonymous field are promoted to become methods -of the enclosing type. In this case, because myChildType has an -anonymous field of type myType, the methods of -myType also become methods of myChildType. -In this example, the Get method was -overridden, and the Set method was inherited. -

- -

-This is not precisely the same as a child class in C++. -When a method of an anonymous field is called, -its receiver is the field, not the surrounding struct. -In other words, methods on anonymous fields are not virtual functions. -When you want the equivalent of a virtual function, use an interface. -

- -

-A variable that has an interface type may be converted to have a -different interface type using a special construct called a type assertion. -This is implemented dynamically -at run time, like C++ dynamic_cast. Unlike -dynamic_cast, there does -not need to be any declared relationship between the two interfaces. -

- -
-type myPrintInterface interface {
-	Print()
-}
-func f3(x myInterface) {
-	x.(myPrintInterface).Print()  // type assertion to myPrintInterface
-}
-
- -

-The conversion to myPrintInterface is entirely dynamic. -It will -work as long as the underlying type of x (the dynamic type) defines -a print method. -

- -

-Because the conversion is dynamic, it may be used to implement generic -programming similar to templates in C++. This is done by -manipulating values of the minimal interface. -

- -
-type Any interface { }
-
- -

-Containers may be written in terms of Any, but the caller -must unbox using a type assertion to recover -values of the contained type. As the typing is dynamic rather -than static, there is no equivalent of the way that a C++ template may -inline the relevant operations. The operations are fully type-checked -at run time, but all operations will involve a function call. -

- -
-type Iterator interface {
-	Get() Any
-	Set(v Any)
-	Increment()
-	Equal(arg Iterator) bool
-}
-
- -

-Note that Equal has an argument of -type Iterator. This does not behave like a C++ -template. See the -FAQ. -

- -

Goroutines

- -

-Go permits starting a new thread of execution (a goroutine) -using the go -statement. The go statement runs a function in a -different, newly created, goroutine. -All goroutines in a single program share the same address space. -

- -

-Internally, goroutines act like coroutines that are multiplexed among -multiple operating system threads. You do not have to worry -about these details. -

- -
-func server(i int) {
-	for {
-		fmt.Print(i)
-		time.Sleep(10 * time.Second)
-	}
-}
-go server(1)
-go server(2)
-
- -

-(Note that the for statement in the server -function is equivalent to a C++ while (true) loop.) -

- -

-Goroutines are (intended to be) cheap. -

- -

-Function literals (which Go implements as closures) -can be useful with the go statement. -

- -
-var g int
-go func(i int) {
-	s := 0
-	for j := 0; j < i; j++ { s += j }
-	g = s
-}(1000)  // Passes argument 1000 to the function literal.
-
- -

Channels

- -

-Channels are used to communicate between goroutines. Any value may be -sent over a channel. Channels are (intended to be) efficient and -cheap. To send a value on a channel, use <- as a binary -operator. To -receive a value on a channel, use <- as a unary operator. -When calling -functions, channels are passed by reference. -

- -

-The Go library provides mutexes, but you can also use -a single goroutine with a shared channel. -Here is an example of using a manager function to control access to a -single value. -

- -
-type Cmd struct { Get bool; Val int }
-func Manager(ch chan Cmd) {
-	val := 0
-	for {
-		c := <-ch
-		if c.Get { c.Val = val; ch <- c }
-		else { val = c.Val }
-	}
-}
-
- -

-In that example the same channel is used for input and output. -This is incorrect if there are multiple goroutines communicating -with the manager at once: a goroutine waiting for a response -from the manager might receive a request from another goroutine -instead. -A solution is to pass in a channel. -

- -
-type Cmd2 struct { Get bool; Val int; Ch <- chan int }
-func Manager2(ch chan Cmd2) {
-	val := 0
-	for {
-		c := <-ch
-		if c.Get { c.ch <- val }
-		else { val = c.Val }
-	}
-}
-
- -

-To use Manager2, given a channel to it: -

- -
-func f4(ch <- chan Cmd2) int {
-	myCh := make(chan int)
-	c := Cmd2{ true, 0, myCh }   // Composite literal syntax.
-	ch <- c
-	return <-myCh
-}
-