diff --git a/doc/docs.html b/doc/docs.html index 171c5cabf5..ccffad8a18 100644 --- a/doc/docs.html +++ b/doc/docs.html @@ -60,7 +60,6 @@ Answers to common questions about Go.
-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. -
- -const or volatile qualifiers.
-
-nil for invalid pointers, where C++ uses
- NULL or simply 0.
--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.
-
-
-
-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 -) -- -
-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. -
- -
-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.
-
-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.
-
-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 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
-}
-