Go Basics: Difference between revisions

From Wiki
Jump to navigation Jump to search
 
(7 intermediate revisions by the same user not shown)
Line 42: Line 42:
go get github.com/nsf/gocode      # grab a remote package and install it to $GOPATH/bin
go get github.com/nsf/gocode      # grab a remote package and install it to $GOPATH/bin
go get -u github.com/nsf/gocode  # update to latest version of remote package
go get -u github.com/nsf/gocode  # update to latest version of remote package
gofmt myfile.go                  # output canonical code format
</pre>
</pre>


Line 174: Line 175:
</source>
</source>


==== Efficient String Append ====
[[Go Strings|Full page on Strings]]
<source lang="go">
var buffer bytes.Buffer
for {
    if piece, ok := getNextValidString(); ok {
        buffer.WriteString(piece)
    } else {
        break
    }
}
fmt.Print(buffer.String(), "\n")
</source>


==== Anatomy of a string ====
=== Pointers ===
[[File:anatomy_of_a_string.jpg]]
<source lang="go">
<source lang="go">
s := "naïve"
z := 37    // z is of type int
fmt.Println(s, len(s))     // prints "naïve 6"
pi := &z  // pi is of type *int (pointer to int)
ppi := &pi // ppi is of type **int (pointer to pointer to int)
fmt.Println(z, pi, *pi, **ppi)  // 37 0xf840038100 37 37
**ppi++    // Semantically the same as: (*(*ppi))++ and *(*ppi)++
fmt.Println(z, pi, *pi, **ppi) // 38 0xf840038100 38 38
</source>
</source>


==== Slicing Strings ====
<source lang="go">
<source lang="go">
line := "røde og gule sløjfer"
func swapAndProduct1(x, y, product *int) {
i := strings.Index(line, " ")     // Get the index of the first space
    *x, *y = *y, *x
firstWord := line[:i]            // Slice up to the first space
     *product = *x * *y // The compiler would be happy with: *product=*x**y
j := strings.LastIndex(line, " ") // Get the index of the last space
}
lastWord := line[j+1:]            // Slice from after the last space
i, j, product := 5, 9, 0
fmt.Println(firstWord, lastWord) // Prints: røde sløjfer
swapAndProduct1(&i, &j, &product)
fmt.Println(i, j, product)           // 9 5 45
</source>
</source>


==== Anatomy of a string with whitespace ====
=== Arrays ===
[[File:anatomy_of_string_whitespace.jpg]]
 
<source lang="go">
<source lang="go">
line := "rå tørt\u2028vær"
var buffer [20]byte
i := strings.IndexFunc(line, unicode.IsSpace)    // i == 3
var grid1 [3][3]int
firstWord := line[:i]
grid1[1][0], grid1[1][1], grid1[1][2] = 8, 6, 2
j := strings.LastIndexFunc(line, unicode.IsSpace) // j == 9
grid2 := [3][3]int{{4, 3}, {8, 6, 2}}
_, size := utf8.DecodeRuneInString(line[j:])      // size == 3
cities := [...]string{"Shanghai", "Mumbai", "Istanbul", "Beijing"}
lastWord := line[j+size:]                         // j + size == 12
cities[len(cities)-1] = "Karachi"
fmt.Println(firstWord, lastWord)                 // Prints: rå vær
</source>


==== <code>fmt</code> print functions ====
fmt.Println("Type    Len Contents")
<source lang="go">
fmt.Printf("%-8T %2d %v\n", buffer, len(buffer), buffer)
fmt.Errorf(format,args...)         // Returns an error value containing a string
fmt.Printf("%-8T %2d %q\n", cities, len(cities), cities)
fmt.Fprint|Fprintf|Fprintln(writer, ...) // Writes to writer
fmt.Printf("%-8T %2d %v\n", grid1, len(grid1), grid1)
fmt.Print|Printf|Println(args...)       // Writes to os.Stdout
fmt.Printf("%-8T %2d %v\n", grid2, len(grid2), grid2)
fmt.Sprint|Sprintf|Sprintln(args...)    // Returns a string
/* Xprint(args...)           concatenate args */
/* Xprintf(format, args...)   print using format */
/* Xprintln(args...)          print args separated by spaces, ending with newline */
</source>
All versions return number of bytes written, and an error or nil.


==== <code>fmt</code> format specifiers ====
Type    Len Contents
<source lang="go">
[20]uint8 20 [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
fmt.Printf("%t %t\n", true, false)                          // true false
[4]string  4 ["Shanghai" "Mumbai" "Istanbul" "Karachi"]
fmt.Printf("|%b|%9b|%-9b|%09b|% 9b|\n", 37, 37, 37, 37, 37)  // |100101|···100101|100101···|000100101|···100101|
[3][3]int 3 [[0 0 0] [8 6 2] [0 0 0]]
fmt.Printf("|%o|%#o|%# 8o|%#+ 8o|%+08o|\n", 41, 41, 41, 41, -41)  // |51|051|·····051|····+051|-0000051|
[3][3]int 3 [[4 3 0] [8 6 2] [0 0 0]]
i := 3931
fmt.Printf("|%x|%X|%8x|%08x|%#04X|0x%04X|\n", i, i, i, i, i, i)  // |f5b|F5B|·····f5b|00000f5b|0X0F5B|0x0F5B|
i = 569
fmt.Printf("|$%d|$%06d|$%+06d|\n", i, i, i) // |$569|$000569|$+00569|
fmt.Printf("%d %#04x %U '%c'\n", 0x3A6, 934, '\u03A6', '\U000003A6') // 934·0x03a6·U+03A6·'Φ'
x = 7194.84
fmt.Printf("%e %f %g\n", x, x, x)                // 7.194840e+03 7194.840000 7194.84
fmt.Printf("%2.4f \n", x)                        // 7194.8400
fmt.Printf("%s %q \n", "hi", "billy")            // hi "billy"
fmt.Printf("|%10s|%-10s|\n", "billy", "billy")    // |    billy|billy    |
fmt.Printf("%T, %T, %T\n", "billy", true, 24.35)  // string, bool, float64
s := "billy"
fmt.Printf("%s's pointer is %p\n", s, &s)        // billy's pointer is 0xf840028220
</source>
</source>

Latest revision as of 23:49, 1 July 2014

Resources: http://golang.org/

Install and Setup

sudo apt-get install golang

http://golang.org/doc/code.html discusses setting up the GOLANG environment variable and your code repository

mkdir -p $HOME/projects/go/src
export GOPATH=$HOME/projects/go (add this to .profile too)

Hello World

// hello.go
package main

import (   
    "fmt"
    "os"
    "strings"
)

func main() {
    who := "World!"  
    if len(os.Args) > 1 { /* os.Args[0] is "hello" or "hello.exe" */  
        who = strings.Join(os.Args[1:], " ")  
    }
    fmt.Println("Hello", who)  
}

Commands

godoc -http=:8000                 # host docs at http://localhost:8000
go build                          # create binary file in local directory
go install                        # create binary file in $GOPATH/bin
go run                            # just run it, disposing of binary
go get github.com/nsf/gocode      # grab a remote package and install it to $GOPATH/bin
go get -u github.com/nsf/gocode   # update to latest version of remote package
gofmt myfile.go                   # output canonical code format

Packages

  • Every file should begin with a package statement.
  • A package may be defined across several files.
  • Code execution begins with a main() function inside package main

Comments

// for end-of-line
/* for multiline */

Constants and Variables

count, err = fmt.Println(x) // get number of bytes printed and error
count, _ = fmt.Println(x)   // get number of bytes printed; discard error
_, err = fmt.Println(x)     // discard number of bytes printed; get error
fmt.Println(x)              // ignore return values
const limit = 512        // constant; type-compatible with any number
const top uint16 = 1421  // constant; type: uint16
start := -19             // variable; inferred type: int
end := int64(9876543210) // variable; type: int64
var i int                // variable; value 0; type: int
var debug = false        // variable; inferred type: bool
checkResults := true     // variable; inferred type: bool
stepSize := 1.5          // variable; inferred type: float64
acronym := "FOSS"        // variable; inferred type: string
i, j := 56, 67   // multiple assignment

Enumerations

const Cyan = 0     // one-per-line
const Magenta = 1
const Yellow = 2

const (            // grouped
    Cyan    = 0
    Magenta = 1
    Yellow  = 2
)

const (            // using iota
    Cyan    = iota // 0
    Magenta        // 1
    Yellow         // 2
)

type BitFlag int   // different example
const (
    Active  BitFlag = 1 << iota            // (1 << 0 == 1)
    Send    // Implicitly BitFlag = 1 << iota (1 << 1 == 2)
    Receive // Implicitly BitFlag = 1 << iota (1 << 2 == 4)
)
flag := Active | Send


Numeric type conversions

const factor = 3 // factor is compatible with any numeric type
i := 20000       // i is of type int by inference
i *= factor
j := int16(20)   // j is of type int16; same as: var j int16 = 20
i += int(j)      // Types must match so conversion is required
k := uint8(0)    // Same as: var k uint8
k = uint8(i)     // Succeeds, but k's value is truncated to 8 bits ✗
fmt.Println(i, j, k) // Prints: 60020 20 116
func Uint8FromInt(x int) (uint8, error) {
    if 0 <= x && x <= math.MaxUint8 {
        return uint8(x), nil
    }
    return 0, fmt.Errorf("%d is out of the uint8 range", x)
}


Types

Boolean

bool (true or false)

Integer

byte (synonym for uint8)
int (int32 or int64)
int8, int16, int32, int64
rune (synonym for int32, used for UTF-8 code points)
uint (uint32 or uint64)
uint8, uint16, uint32, uint64
uintptr (uint that stores a pointer)

Bitwise Operations on Integers

x & y	// The bitwise AND of x and y
x | y	// The bitwise OR of x and y
x ^ y	// The bitwise XOR of x and y
x &^ y	// The bitwise clear (AND NOT) of x and y
x << u	// The result of left-shifting x by unsigned int u shifts
x >> u	// The result of right-shifting x by unsigned int u shifts

Floating-Point

float32, float64
complex64, complex128

f := 3.2e5                       // type: float64
x := -7.3 - 8.9i                 // type: complex128 (literal)
y := complex64(-18.3 + 8.9i)     // type: complex64 (conversion) 
z := complex(f, 13.2)            // type: complex128 (construction) 
fmt.Println(x, real(y), imag(z)) // Prints: (-7.3-8.9i) -18.3 13.2

Strings

text1 := "\"what's that?\", he said" // Interpreted string literal
text2 := `"what's that?", he said`   // Raw string literal
radicals := "√ \u221A \U0000221a"    // radicals == "√ √ √"
book := "The Spirit Level" +                     // String concatenation
        " by Richard Wilkinson"
book += " and Kate Pickett"                      // String append
fmt.Println("Josey" < "José", "Josey" == "José") // String comparisons

Full page on Strings

Pointers

z := 37    // z is of type int
pi := &z   // pi is of type *int (pointer to int)
ppi := &pi // ppi is of type **int (pointer to pointer to int)
fmt.Println(z, pi, *pi, **ppi)  // 37 0xf840038100 37 37
**ppi++    // Semantically the same as: (*(*ppi))++ and *(*ppi)++
fmt.Println(z, pi, *pi, **ppi)  // 38 0xf840038100 38 38
func swapAndProduct1(x, y, product *int) {
    *x, *y = *y, *x
    *product = *x * *y // The compiler would be happy with: *product=*x**y
}
i, j, product := 5, 9, 0
swapAndProduct1(&i, &j, &product)
fmt.Println(i, j, product)            // 9 5 45

Arrays

var buffer [20]byte
var grid1 [3][3]int
grid1[1][0], grid1[1][1], grid1[1][2] = 8, 6, 2
grid2 := [3][3]int{{4, 3}, {8, 6, 2}}
cities := [...]string{"Shanghai", "Mumbai", "Istanbul", "Beijing"}
cities[len(cities)-1] = "Karachi"

fmt.Println("Type     Len Contents")
fmt.Printf("%-8T %2d %v\n", buffer, len(buffer), buffer)
fmt.Printf("%-8T %2d %q\n", cities, len(cities), cities)
fmt.Printf("%-8T %2d %v\n", grid1, len(grid1), grid1)
fmt.Printf("%-8T %2d %v\n", grid2, len(grid2), grid2)

Type     Len Contents
[20]uint8 20 [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[4]string  4 ["Shanghai" "Mumbai" "Istanbul" "Karachi"]
[3][3]int  3 [[0 0 0] [8 6 2] [0 0 0]]
[3][3]int  3 [[4 3 0] [8 6 2] [0 0 0]]