表紙 編集 差分 一覧 最近 短縮 付箋 ログイン 凍結中

Go言語学習帳

N2Wiki > Go言語学習帳

一覧 [非表示]

Go言語で写経してゆくページ。[Go]

環境構築

  1. Portable Ubuntu
    • 8.04→8.10→9.04
  2. Goのインストール

HelloWorld

package main
import "fmt"

func main() {
    fmt.Printf("Hello, world!\n");
}

Ackermann

package main
import "fmt"

func main() {
    fmt.Printf("ack(3,9): %d \n",ack(3,9));
}

func ack(m, n int) int {
    switch {
        case m == 0: return n+1;
        case n == 0: return ack(m-1, 1);
    }
    return ack(m-1, ack(m, n-1));
}
  • default: return ack(m-1, ack(m, n-1)); と書くと「returnがない」と叱られる。

AccumulatorGenerator

package main
import "fmt"

func main() {
    f := accgen(10);
    a := f(1);
    b := f(2);
    fmt.Printf("a: %d, b: %d \n",a,b);
}

func accgen(n int) (func(int) int) {
    return func(x int) int {
        n += x;
        return n;
    };
}
  • あとで気づいたけどtestのclosure.goの中にあった。
  • return n += x; と書くと叱られます。

BankAccount

package main
import "fmt"

type BankAccountInterface interface {
    set(x float);
    get() float;
}

func deposit(b BankAccountInterface, x float) {
    b.set(b.get() + x);
}

func withdraw(b BankAccountInterface, x float) {
    dollars := b.get() - x;
    if dollars < 0 { dollars = 0; }
    b.set(dollars);
}

type bankAccount struct {
    dollars float;
}

func (b *bankAccount) set(x float) {
    b.dollars = x;
}

func (b *bankAccount) get() float {
    return b.dollars;
}

type stockAccount struct {
    numShares float;
    pricePerShare float;
}

func (b *stockAccount) get() float {
    return b.pricePerShare * b.numShares;
}

func (b *stockAccount) set(x float) {
    b.numShares = x / b.pricePerShare;
}

func p(v ...) { 
    fmt.Println(v);
}

func main() {
    account := &bankAccount{200};
    p(account.get());
    deposit(account,50);
    p(account.get());
    withdraw(account,100);
    p(account.get());
    withdraw(account,200);
    p(account.get());
    
    stock := &stockAccount{10, 30};
    p(stock.numShares);
    p(stock.pricePerShare);
    p(stock.get());
    stock.set(150);
    p(stock.numShares);
    stock.set(600);
    p(stock.get());
    p(stock.numShares);
    deposit(stock,60);
    p(stock.get());
    p(stock.numShares);
}
  • もっとGoらしい書き方というものがあるのかもしれない・・・
  • クラスベースオブジェクト指向の考え方から頭を切り替えないとはまる。
    • かといってプロトタイプベースでもない。

FluentInterface

package main
import "fmt"

type myType struct { i int; }

type fluent interface {
    p() fluent;
    add(n int) fluent;
}

func (self *myType) p() fluent {
    fmt.Println(self.i);
    return self;
}

func (self *myType) add(n int) fluent {
    self.i += n;
    return self;
}

type fluent2 interface {
    fluent;
    sub(n int) fluent2;
}   

func (self *myType) sub(n int) fluent2 {
    self.i -= n;
    return self;
}

func main() {
    x := &myType{10};
//    x.sub(2).p().add(10).p().sub(3).p(); // error!
    x.sub(2).p().add(10).p().(fluent2).sub(3).p(); // type assertion

}
  • receiverにはInterfaceを書けない。
  • 戻り値の型にはInterfaceが書ける。
  • Interfaceは継承(?)できる。
  • Interfaceに定義されていないメソッドを呼ぼうとするとコンパイルエラー
  • Type Assertionするとコンパイルが通り実行時に型変換。
  • Google先生、SelfTypeか型変数がほしいです・・・。

fix

package main
import "fmt"

type unaryFunc func (int) int;

func fibMaker(f unaryFunc) unaryFunc {
    return func (x int) int {
        if x <= 1 {
            return 1
        }
        return f(x-1) + f(x-2);
    };
}

func fix(g func (unaryFunc) unaryFunc) unaryFunc {
    return g(func(x int) int { return fix(g)(x) });
}

func main() {
    fib := fix(fibMaker);
    for i := 1; i < 6; i++ {
        fmt.Println(fib(i));
    }
}

decorator

package main
import "fmt"

type staff struct {
    payment float;
}

type employee interface {
    getOvertimePay() float;
}

func showOvertimePay(e employee, name string) {
    fmt.Printf("%s: I'm getting %f yen. Haha!\n", 
        name, e.getOvertimePay()
    );
}

func (self *staff) getOvertimePay() float {
    return self.payment;
}

type beTechnical struct {
    prototype employee;
}

func (self *beTechnical) getOvertimePay() float {
    return self.prototype.getOvertimePay() * 1.1;
}

type beLicensed struct {
    prototype employee;
}

func (self *beLicensed) getOvertimePay() float {
    return self.prototype.getOvertimePay() * 1.2;
}

type beManager struct {
    prototype employee;
}

func (self *beManager) getOvertimePay() float {
    return 0;
}

type beTemporary struct {
    prototype employee;
}

func (self *beTemporary) getOvertimePay() float {
    return 1000;
}

func main() {
    john := &beTechnical{&beLicensed{&staff{1000}}};
    showOvertimePay(john, "John");
    
    elen := &beTemporary{&beTechnical{&staff{1000}}};
    showOvertimePay(elen, "Elen");
}

FizzBuzz

package main
import "fmt"

func natsGen() chan int {
    ch := make(chan int);
    go func() {
        for i := 1; ; i++ {
            ch <- i
        }
    }();
    return ch;
}

func fizzGen() chan string {
    ch := make(chan string);
    go func() {
        for {
            ch <- "";
            ch <- "";
            ch <- "Fizz";
        }
    }();
    return ch;
}

func buzzGen() chan string {
    ch := make(chan string);
    go func() {
        for {
            ch <- "";
            ch <- "";
            ch <- "";
            ch <- "";
            ch <- "Buzz";
        }
    }();
    return ch;
}

func fizzBuzz() chan string {
    out := make(chan string);
    go func() {
        nats := natsGen();
        fizz := fizzGen();
        buzz := buzzGen();
        for {
            n := <- nats;
            f := <- fizz;
            b := <- buzz;
            if f != "" || b != "" {
                out <- f + b;
            }
            else {
                out <- fmt.Sprintf("%d", n);
            }
        }
    }();
    return out;
}

func main() {
    fizzbuzz := fizzBuzz();
    for i := 1 ; i <= 30 ; i++ {
        fmt.Println(<-fizzbuzz);
    }
}

Fibonacci

package main
import "fmt"

func fibonacci() chan int {
    ch := make(chan int);
    go func() {
        a := 0;
        b := 1;
        for {
            a, b = b, a+b;
            ch <- a;
        }
    }();
    return ch;
}

func main() {
    fibs := fibonacci(); 
    for i := 0 ; i < 34 ; i++ {
        fmt.Println(<-fibs);
    }
}