Benutzer-Werkzeuge

Webseiten-Werkzeuge


becki:linux:golang

Go Programming Language Tips

Setup

Download Go source:

cd /usr/local
hg clone -r release https://go.googlecode.com/hg/ go

Build Toolchain:

cd go/src
./all.bash

Add Go tools to PATH by creating /etc/profile.de/go.sh:

#!/bin/sh
export PATH="$PATH:/usr/local/go/bin"
export GOROOT=/usr/local/go

Go Syntax Highlighting for your editor at http://go-lang.cat-v.org/text-editors/

Go Syntax Highlighting for your dokuwiki at http://rosettacode.org/wiki/User:MizardX/GeSHi_Go.php (Doesn't work with 2009-12-25c „Lemming“)

Updating Go is described here

ARM5 (Sheevaplug) specific

  • Current release version (release.r57.1 / 8295:95d2ce135523) does not work
  • Current weekly version (weekly.2011-06-02 / 8624:3418f22c39eb) works
  • export GOARM=5 in ~/.profile !
  • export GOHOSTARCH=arm, export GOHOSTOS=linux, export GOARCH=arm, export GOOS=linux may be necessary too

Build Crosscompiler on x86 for ARM5

Export the following variables before running src/all.bash:

export GOROOT=$(pwd)
export GOHOSTARCH=386
export GOHOSTOS=linux
export GOARCH=arm
export GOOS=linux
export GOARM=5

Hello World

package main
import "fmt"
 
func main() {
    fmt.Printf("Hallo  Süße!\n")
}

Build & run:
x86: 8g hello.go && 8l -o hello hello.8 && ./hello

arm: 5g hello.go && 5l -o hello hello.5 && ./hello

For Printf see pkg/fmt/

Command Line Arguments

Use the os.Args slice. Source

Exit Code

Use os.Exit().

return in main() only works without any argument, which results in 0 as exit code (tested).

Standard Streams

FIXME

Variable Declaration

package main
import "fmt"
func main() {
    var i,j int                         // 2 ints, autoinitialized to zero value
    fmt.Printf("%d %d\n", i, j)         // 0 0 
 
    var k,l,m,n= true, 0, 2.6, "Hello"  // missing types default to:
    fmt.Printf("%T %T %T %T\n",k,l,m,n) // -> bool int float64 string
    fmt.Printf("%v %v %v %v\n",k,l,m,n) // -> true 0 2.6 Hello
    fmt.Println(k,l,m,n)                // -> true 0 2.6 Hello
 
    o,p:= false, "World"                // short form: no type but initializers:
    fmt.Printf("%T %T\n", o, p)         // -> bool string
    fmt.Println(o,p)                    // -> false World
}

more

Arrays

a := [...]int{0, 1, 2, 3}           // an array created literally
a := [4]int                         // create a zeroed array (?)
package main
import "fmt"
func main() {
    //var ia= [...]int{47, 11}      // Create an array literal
    ia:= [...]int{47,11}            // Create an array literal - short form
 
    for i, v := range ia {          // Loop through an array
        fmt.Printf("%d %d\n", i, v)
    }
 
    var ib [3]int                   // Create arrays with ZEROED elements
    var ic [2]int
    for _, v := range ib {          // '_' means key not used
        fmt.Printf("%d \n", v)      // -> 0 0 0
    }
 
    //i=0                           // illegal, i not defined outside loop
    //ib = ia                       // illegal, different len => different types
    //ib[3]=9                       // illegal, index out of bounds
    //fmt.Println(ia == ic)         // illegal, no == operator for array
 
    ic= ia                          // copy BY VALUE
    ia[0]= 36
    fmt.Println(ia, ic)             // -> [36 11] [47 11]
 
    //i:=3
    //ib[i]=9                       // panic => runtime index check :-)
}
  • The length of the array is part of its type and cannot grow
  • Arrays are real types
  • Arrays are copied by value :!:
  • A Pointer to an array is possible (unlike in C where the pointer represents the array)

Slices

s := []int{0, 1, 2, 3}                  // a slice created literally
s := make([]int, 4)                     // create a zerored slice
len(s) // get number of items in slice
cap(s) // get actual slice capacity
package main
import "fmt"
func main() {
    a:= [...]int{0, 1, 2, 3}            // an array to play with
    sa:= a[:]                           // Create slice from whole array
    sb:= a[:2]                          // Create slice from first part
    sc:= a[2:]                          // Create slice from last part
    fmt.Println(sa, len(sa), cap(sa))   // -> [0 1 2 3] 4 4
    fmt.Println(sb, len(sb), cap(sb))   // -> [0 1] 2 4(!)
    fmt.Println(sc, len(sc), cap(sc))   // -> [2 3] 2 2
 
    sa[0]=6                             // all slices point to the same array:
    sb[1]=7                             //
    sc[0]=8                             //
    a[3]= 9                             //
    fmt.Println(a, sa, sb, sc)          // -> [6 7 8 9] [6 7 8 9] [6 7] [8 9]
 
    //sb[2]=7                           // panic, although cap is 4!
 
    sb= sa                              // A copy points to the same array:
    fmt.Println(a, sa, sb)              // -> [6 7 8 9] [6 7 8 9] [6 7 8 9]
    sb[0]=0                             //
    fmt.Println(a, sa, sb)              // -> [0 7 8 9] [0 7 8 9] [0 7 8 9]
 
    // fmt.Println(sb==sa)              // invalid, works only with nil
 
    sc= append(sb, 5)                   // append() can create new array:
    fmt.Println(sa, sb, sc)             // -> [0 7 8 9] [0 7 8 9] [0 7 8 9 5]
    sa[1]= 1                            //
    sb[2]= 2                            //
    fmt.Println(sa, sb, sc)             // -> [0 1 2 9] [0 1 2 9] [0 7 8 9 5]
}
  • Slices are copied by value but the internal arrays are copied by reference :!:
  • Slices have a length (number of items) and a capacity (length of underlying array(?))
Appending to a Slice results in a new slice. The new slice may point to a different array than the original slice.

more

Objects

Copying Objects

type Point struct {
    x, y int
}
 
func main() {
    p:= Point{}
    fmt.Println(p)                      // -> {0 0}
 
    c:= p
    p.y= 1
    c.x= 2
    fmt.Println(p, c)                   // -> {0 1} {2 0}
}
Objects are copied by value

Methods

/** A method which has a copy of its object as receiver: */
func (pt Point) SetWithVal(x, y int) {
    pt.x= x
    pt.y= y
}
 
/** A method which has a pointer to its object as receiver: */
func (pt *Point) Set(x, y int) {
    pt.x= x
    pt.y= y
}
 
func main() {
    p:= Point{}
 
    /* invoking both methods on an object: */
    ov:= p
    ov.SetWithVal(1, 2)                 // -> SetWithVal operates only on copy!:
    fmt.Println(ov)                     // -> {0 0}
    ov.Set(3, 4)                        // -> Set works as expected:
    fmt.Println(ov)                     // -> {3 4}
 
    /* invoking both methods on pointer to object: */
    op:= &p
    op.SetWithVal(5, 6)                 // -> SetWithVal operates only on copy!:
    fmt.Println(op)                     // -> &{0 0}
    op.Set(7, 8)                        // -> Set works as expected:
    fmt.Println(op)                     // -> &{7 8}
 
    /* As expected, canges to the pointer change also the object pointed to: */
    fmt.Println(p)                      // -> {7 8}
}
  • In order to really work on the object, the receiver of the method must be a pointer to the object, otherwise the method operates ony on an (anonymous) copy.
  • Invoking methods on pointers to objects has the same syntax and work the same as invoking the method directly on the object.

Interfaces

type Point struct {
    x, y int
}
 
func (pt Point) SetWithVal(x, y int) {
    pt.x= x
    pt.y= y
}
 
func (pt *Point) Set(x, y int) {
    pt.x= x
    pt.y= y
}
 
type SetWithVal_i interface {
    SetWithVal(x, y int)
}
 
type Set_i interface {
    Set(x, y int)
}
 
func main() {
    var isp Set_i
    var isv SetWithVal_i
    fmt.Printf("%T %T\n", isp, isv)     // <nil> <nil>
 
    o:= Point{}
    isv= o                              // isv is an independent COPY of o:
    fmt.Printf("%T\n", isv)             // -> main.Point
    o.x= 9                              // but the copy
    isv.SetWithVal(1, 1)                // can't be modified via isv:
    fmt.Println(o, isv)                 // -> {9 0} {0 0}
 
    o= Point{}                          // reset to {0 0}
    isv= &o                             // isv now is a POINTER(!) to o:
    fmt.Printf("%T\n", isv)             // -> *main.Point
    o.x= 9                              // updates to object are seen by isv
    isv.SetWithVal(2, 2)                // but object can't be modified via isv:
    fmt.Println(o, isv)                 // -> {9 0} &{9 0}
 
    o= Point{}                          // reset to {0 0}
    //isp= o                            // Err! Set_i.Set needs pointer receiver
 
    isp= &o                             // isp now points to o:
    fmt.Printf("%T\n", isp)             // -> *main.Point
    isp.Set(3, 3)                       // object can be modified via interface
    o.y= 4                              // and vice versa:
    fmt.Println(o, isp)                 // -> {3 4} &{3 4}
}
An Interface can store any value that implemts it. This can be a value or a pointer to a value.

The only way to directly operate on an object via an interface is to

  • Implement the methods of the interface with an object pointer as receiver
  • Instantiate the interface with the adress of the object
Some :?: library functions which return an interface in reality return a pointer to an implementation of the interface (see e.g. net.Listen)

Handling Errors

Defer, Panic, Recover: http://blog.golang.org/2010_08_01_archive.html ⇒ The convention in the Go libraries is that even when a package uses panic internally, its external API still returns explicit os.Error values.

os.Error is the same interface as fmt.Stringer, i.e. it has a method called String() wich returns a string. Thus an instance of os.Error can always be passed to the functions in fmt and log directly, without explicitely calling the String() method. E.g:

if err != nil {
    log.Panic(err)
}

FIXME See Exception Handling in C

Unsorted Things

  • Since strings are immutable values I guess only references are passed around if you pass the type string. Thus it probably does not make much sense to use pointers to strings.
  • Seems to be convention that a function returns (among others) os.Error == nil when it succeded (tested)
  • if and switch accept an initialization statement, see doc/effective_go.html#if
  • Number ⇔ String conversion is done with pkg/strconv/

Todo

  • Where is variable argument list for functions?
  • Where is basename?
  • Type Conversions look like function calls, see doc/go_spec.html#Conversions
  • Check type assertion, eg. s, ok := v.(Stringer), see Tutorial
Cookies helfen bei der Bereitstellung von Inhalten. Diese Website verwendet Cookies. Mit der Nutzung der Website erklären Sie sich damit einverstanden, dass Cookies auf Ihrem Computer gespeichert werden. Außerdem bestätigen Sie, dass Sie unsere Datenschutzerklärung gelesen und verstanden haben. Wenn Sie nicht einverstanden sind, verlassen Sie die Website. Weitere Information
becki/linux/golang.txt · Zuletzt geändert: 2018-02-26 11:24 von becki

Impressum - Datenschutzerklärung