package main import ( "fmt" "net/http" ) func handler(w http.ResponseWriter, r *http.Request){ fmt.Fprintf(w, "Hi %s!", r.URL.Path[1:]) } func main(){ http.HandleFunc("/", handler) http.ListenAndServe(":8080", nil) }
A Tour to Go
The rule is that public functions, types, etc., should be upper case.
Variable
package main import "fmt" func main(){ var msg string msg = "hello world" fmt.Println(msg) msg := "hello world" fmt.Println(msg) a, b:= 10, 15 }
基本データ型
package main import "fmt" func main(){ a := 10 b := 12.3 c := "hoge" var d bool fmt.Printf("a: %d, b:%f, c:%s, d:%t\n", a, b, c, d) }
const, iota: https://github.com/golang/go/wiki/Iota
package main import "fmt" func main(){ // const name = "yoshida" // name = "tanaka" const ( sun = iota mon tue ) fmt.Println(sun, mon, tue) }
pointer
package main import "fmt" func main(){ a := 5 var pa *int pa = &a // a address fmt.Println(pa) fmt.Println(*pa) }
function
package main import "fmt" func hi(name string) string{ msg := "hi!" + name return msg } func main(){ fmt.Println(hi("tanaka")) }
swap
package main import "fmt" func swap(a, b int)(int, int){ return b, a } func main(){ fmt.Println(swap(5, 2)) }
array
a := [...]int{1, 3, 5} a := [5]int{1, 3, 5, 8, 9} s := a[2:4] fmt.Println(s) fmt.Println(len(s)) fmt.Println(cap(s)) s := []int{1, 3, 5} s = append(s, 8, 2, 10) t := make([]int, len(s)) n := copy(t, s)
map
m := make(map[string]int) m["tanaka"] = 200 m["sato"] = 300 fmt.Println(m)
if
score := 83 if score > 80 { fmt.Println("great") } else { fmt.Println("soso") }
range
s := []int{2, 3, 8} for i, v := range s{ fmt.Println(i, v)
構造体
type user struct { name string score int } func main(){ u := new(user) u.name = "tanaka" fmt.Println(u) }
go routine
package main import ( "fmt" "time" ) func task1(){ time.Sleep(time.Second * 2) fmt.Println("task1 finished!") } func task2(){ fmt.Println("task2 finished!") } func main(){ go task1() go task2() time.Sleep(time.Second * 3) }
Getting started with Go lang
Go is a cool programming language. Check out golang.org
install:sudo yum install golang
[vagrant@localhost go]$ go version go version go1.7.3 linux/amd64
package main import "fmt" func main(){ fmt.Println("hello world") }
Go言語では、go buildでコンパイルしますが、go run xxx.goの1行で、実行することも可能です。
[vagrant@localhost go]$ go build hello.go [vagrant@localhost go]$ ls hello hello.go [vagrant@localhost go]$ ./hello hello world [vagrant@localhost go]$ go run hello.go hello world
mono-opt インストール
centOSによるC#の実行環境を整えるため、monoの公式サイトより、Linux向けインストールを実行します。
cd /etc/yum.repos.d yum install epel-release wget https://copr.fedoraproject.org/coprs/tpokorra/mono-opt/repo/epel-6/tpokorra-mono-opt-epel-6.repo yum install monodevelop-opt nunit-opt . /opt/mono/env.sh mono --version
[vagrant@localhost yum.repos.d]$ mono --version Mono JIT compiler version 4.6.0 (Stable 4.6.0.245/746756c Sat Sep 24 06:33:41 UTC 2016) Copyright (C) 2002-2014 Novell, Inc, Xamarin Inc and Contributors. www.mono-project.com TLS: __thread SIGSEGV: altstack Notifications: epoll Architecture: amd64 Disabled: none Misc: softdebug LLVM: yes(3.6.0svn-mono-/) GC: sgen
Monoのコンパイルコマンド
[vagrant@localhost csharp]$ mcs MyApp.cs [vagrant@localhost csharp]$ ls MyApp.cs MyApp.exe [vagrant@localhost csharp]$ mono MyApp.exe
迷路
左上を迷路のスタート地点、右下を迷路のゴール地点とし、0と1の配列で道と壁を作成しています。迷路作成のアルゴリズムは、棒倒し法で記載しています。考えた人は天才ですね。。
棒倒し法
1.一つとびに壁を作る 1れつ目の棒を上下左右のどちらかに倒す
2.2列目以降の棒を左以外のどれかに倒す
00010
11010
00000
01011
01000
どの位置を0から1に変更するかは、以下のように記載します。
var points = [
[0, -1],
[0, 1],
[1, 0],
[-1, 0],
];
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>MAZE</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="styles.css"> <style> body { font-family: "Century Gothic"; font-size: 16px; } #container { text-align: center; margin: 20px auto; } #mycanvas { background: #AAEDFF; } .btn { margin: 3px auto; width: 200px; padding: 5px; background: #00AAFF; color: #ffffff; border-radius:3px; cursor: pointer; } .btn:hover{ opacity: 0.8; } </style> </head> <body> <div id="container"> <canvas width="100" height="100" id="mycanvas"> Canvasに対応したブラウザを用意してください。 </canvas> <div id="reset" class="btn">RESET</div> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script> <script> (function(){ var Maze = function(col, row){ this.map = []; this.col = col; this.row = row; this.startX = 0; this.startY = 0; this.goalX =col - 1; this.goalY =row - 1; this.points = [ [0, -1], [0, 1], [1, 0], [-1, 0], ]; this.rand = function(n) { return Math.floor(Math.random() * (n + 1)); }; this.init = function() { for (var x = 0; x < col; x++) { this.map[x] = []; for (var y = 0; y < row; y++) { this.map[x][y] = 0; } } for (var x = 1; x < col; x += 2) { for (var y = 1; y < row; y += 2) { this.map[x][y] = 1; } } for (var x = 1; x < col; x += 2) { for (var y = 1; y < row; y += 2) { do { if (x === 1) { // 上下左右に倒す var r = this.points[this.rand(3)]; } else { // 左以外に倒す var r = this.points[this.rand(2)]; } } while (this.map[x + r[0]][y + r[1]] === 1); this.map[x + r[0]][y + r[1]] = 1; } } }; this.draw = function() { var view = new View(); view.draw(this); }; }; var View = function(){ this.wallSize = 10; this.wallColor = '#3261AB'; this.routeColor = '#ff0088'; this.canvas = document.getElementById('mycanvas'); if (!this.canvas || !this.canvas.getContext){ return false; } this.ctx = this.canvas.getContext('2d'); this.draw = function(maze){ this.canvas.width = (maze.col + 2) * this.wallSize; this.canvas.height = (maze.row + 2) * this.wallSize; // 上下の壁 for (var x = 0; x < maze.col + 2; x++) { this.drawWall(x, 0); this.drawWall(x, maze.row + 1); } // 左右の壁 for (var y = 0; y < maze.row + 2; y++) { this.drawWall(0, y); this.drawWall(maze.col + 1, y); } // 迷路の内部 for (var x = 0; x < maze.col; x++){ for(var y = 0; y < maze.row; y++){ if(maze.map[x][y] === 1){ this.drawWall(x + 1, y + 1); } if ((x === maze.startX && y === maze.startY) || (x === maze.goalX && y === maze.goalY)) { this.drawRoute(x + 1, y + 1); } } } }; this.drawWall = function(x, y) { this.ctx.fillStyle = this.wallColor; this.drawRect(x, y); }; this.drawRoute = function(x, y) { this.ctx.fillStyle = this.routeColor; this.drawRect(x, y); }; this.drawRect = function(x, y){ this.ctx.fillRect( x * this.wallSize, y * this.wallSize, this.wallSize, this.wallSize); }; }; function reset(){ var maze = new Maze(13, 13); maze.init(); maze.draw(); } reset(); document.getElementById('reset').addEventListener('click', function(){ reset(); }); // // 迷路のデータを配列で用意 // // 0と1の配列で、1を壁と表現する ※奇数でないと道ができない // // canvasで描画 // // 棒倒し法 // // 一つとびに壁を作る 1れつ目の棒を上下左右のどちらかに倒す // // 2列目以降の棒を左以外のどれかに倒す // // 00010 // // 11010 // // 00000 // // 01011 // // 01000 // var map = []; // // map[0] = [0, 0, 0]; // // map[1] = [0, 1, 1]; // // map[2] = [0, 0, 0]; // var col = 13; // 奇数 // var row = 13; // 奇数 // for (var x = 0; x < col; x++){ // map[x] = []; // for (var y = 0; y < row; y++){ // map[x][y] = 0; // } // } // for (var x = 1; x < col; x += 2){ // for(var y = 1; y < row; y += 2){ // map[x][y] = 1; // } // } // var points = [ // [0, -1], // [0, 1], // [1, 0], // [-1, 0], // ]; // function rand(n){ // return Math.floor(Math.random() * (n + 1)); // } // for (var x = 1; x < col; x += 2){ // for(var y = 1; y < row; y += 2){ // map[x][y] = 1; // do { // if (x === 1){ // var r = points[rand(3)]; // } else { // var r = points[rand(2)]; // } // } while (map[x + r[0]][y + r[1]] === 1); // map[x + r[0]][y + r[1]] = 1; // } // } // var startX = 0; // var startY = 0; // var goalX =col - 1; // var goalY =row - 1; // var wallSize = 10; // var wallColor = '#3261AB'; // var routeColor = '#ff0088'; // var canvas = document.getElementById('mycanvas'); // if (!canvas || !canvas.getContext){ // return false; // } // var ctx = canvas.getContext('2d'); // canvas.width = (col + 2) * wallSize; // canvas.height = (row + 2) * wallSize; // // 上下の壁 // for (var x = 0; x < col + 2; x++) { // drawWall(x, 0); // drawWall(x, row + 1); // } // // 左右の壁 // for (var y = 0; y < row + 2; y++) { // drawWall(0, y); // drawWall(col + 1, y); // } // // 迷路の内部 // for (var x = 0; x < col; x++){ // for(var y = 0; y < row; y++){ // if(map[x][y] === 1){ // drawWall(x + 1, y + 1); // } // if ((x === startX && y === startY) || (x === goalX && y === goalY)) // { // drawRoute(x + 1, y + 1); // } // } // } // // 壁を描画 // function drawWall(x, y) { // ctx.fillStyle = wallColor; // drawRect(x, y); // } // function drawRoute(x, y) { // ctx.fillStyle = routeColor; // drawRect(x, y); // } // function drawRect(x, y){ // ctx.fillRect( // x * wallSize, // y * wallSize, // wallSize, // wallSize); // } })(); </script> </body> </html>
pinpongゲーム
canvasを使って、x座標、y座標で、setTime関数で動かしています。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Pong Game</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="styles.css"> <style> body { margin: 0; font-family: "Century Gothic"; font-size: 16px; } #container { text-align: center; margin: 5px auto; } #mycanvas { background: #AAEDFF; } #btn { margin: 3px auto; width: 200px; padding: 5px; background: #00AAFF; color: #FFFFFF; border-radius: 3px; cursor: pointer; } #btn:hover { opacity: 0.8; } </style> </head> <body> <div id="container"> <canvas width="280" height="280" id="mycanvas"> Canvasに対応したブラウザを用意してください。 </canvas> <div id="btn">START</div> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script> <script> $(function(){ var ctx, myPaddle, myBall, mouseX, score, scoreLabel, isPlaying = false, timerId; var canvas = document.getElementById('mycanvas'); if (!canvas|| !canvas.getContext) return false; ctx = canvas.getContext('2d'); var Label = function(x, y){ this.x = x; this.y = y; this.draw = function(text){ ctx.font = 'bold 14px "Century Gothic"'; ctx.fillStyle = '#00AAFF'; ctx.textAlign = 'left'; ctx.fillText(text, this.x, this.y); } } var Ball = function(x, y, vx, vy, r){ this.x = x; this.y = y; this.vx = vx; this.vy = vy; this.r = r; this.draw = function(){ ctx.beginPath(); ctx.fillStyle = '#FF0088'; ctx.arc(this.x, this.y, this.r, 0, 2*Math.PI, true); ctx.fill(); }; this.move = function(){ this.x += this.vx; this.y += this.vy; if (this.x + this.r > canvas.width || this.x - this.r < 0){ this.vx *= -1; } if (this.y - this.r < 0){ this.vy *= -1; } if (this.y + this.r > canvas.height){ // alert("game over"); isPlaying = false; $('#btn').text('REPLAY?').fadeIn(); } }; this.checkCollision= function(paddle){ if ((this.y + this.r > paddle.y && this.y + this.r < paddle.y + paddle.h) && (this.x > paddle.x - paddle.w / 2 && this.x < paddle.x + paddle.w /2)){ this.vy *= -1; score++; if (score % 2 === 0){ this.vx *= 1.3; paddle.w *= 0.9; } } } } var Paddle = function(w, h){ this.w = w; this.h = h; this.x = canvas.width / 2; this.y = canvas.height - 30; this.draw = function(){ ctx.fillStyle = '#00AAFF'; ctx.fillRect(this.x - this.w / 2, this.y, this.w, this.h); }; this.move = function(){ this.x = mouseX - $('#mycanvas').offset().left; } }; function rand(min, max){ return Math.floor(Math.random() * (max - min + 1)) + min; } function init(){ score = 0; isPlaying = true; myPaddle = new Paddle(100, 10); myBall = new Ball(rand(50, 250), rand(10, 80), rand(3, 8), rand(3, 8), 6); scoreLabel = new Label(10, 25); scoreLabel.draw('SCORE: ' + score); } function clearStage(){ ctx.fillStyle = '#AAEDFF'; ctx.fillRect(0, 0, canvas.width, canvas.height); } function update(){ clearStage(); scoreLabel.draw('SCORE: ' + score); myPaddle.draw(); myPaddle.move(); myBall.draw(); myBall.move(); myBall.checkCollision(myPaddle); timerId =setTimeout(function(){ update(); }, 30); if(!isPlaying) clearTimeout(timerId); } $('#btn').click(function(){ $(this).fadeOut(); init(); update(); }); $('body').mousemove(function(e){ mouseX = e.pageX; }); }); </script> </body> </html>
rpsecによるリファクタリング
require 'calc' RSpec.describe "A calc" do before do @calc = Calc.new end it "given 2 and 3, returns 5" do expect(@calc.add(2, 3)).to eq(5) end it "given 5 and 8, returns 13" do expect(@calc.add(5, 8)).to eq(13) end end
class Calc def add(a, b) a + b # 仮実装 end end
[vagrant@localhost rspec]$ rspec .. Finished in 0.00235 seconds (files took 0.11087 seconds to load) 2 examples, 0 failures
describeはcontextを書き換えることも可能。また、コマンドラインはrspec -fdとしても使われる。
pendding
require 'calc' RSpec.describe Calc do describe "when normal mode" do it "given 2 and 3, returns 5" do calc = Cal.new expect(calc.add(2, 3)).to eq(5) end describe "when graph mode" do it "draws graph" do end end
matcher:https://www.relishapp.com/rspec/rspec-expectations/docs/built-in-matchers
expect(calc.add(2, 3)).to eq(5) #matcher expect(calc.add(2, 3)).not_to eq(5) #matcher expect(calc.add(2, 3)).to be true #matcher expect(calc.add(2, 3)).to be false #matcher expect(calc.add(2, 3)).to be > 10 #matcher expect(calc.add(2, 3)).to be_between(1, 10).include #matcher expect(calc).to respond_to(:add) #matcher expect(calc.add(2, 3).integer?).to be true
subject
require 'calc' RSpec.describe Calc do subject(:calc){ Calc.new } it { # calc = Calc.new expect(calc.add(2, 3)).to eq(5) } end
let
context "tax 5%" do let(:tax){ 0.05 } it { expect(calc.price(100, tax)).to eq(105)} end context "tax 8%" do let(:tax){ 0.08 } it { expect(calc.price(100, tax)).to eq(108)} end
message expectation
class Calc def initialize(logger) @logger = logger end def add(a, b) @logger.log a + b end end
rspecによるBDD
rspec install
[vagrant@localhost rspec]$ gem install rspec [vagrant@localhost rspec]$ ruby -v ruby 2.3.1p112 (2016-04-26 revision 54768) [x86_64-linux] [vagrant@localhost rspec]$ rspec -v 3.5.4
TDD/BDD 開発サイクル
1.失敗するテストを書く(Red)
2.最小限のコードを書いてテストをパスさせる(Green)
3.リファクタリング
initフォルダの作成
[vagrant@localhost rspec]$ rspec --init create .rspec create spec/spec_helper.rb
テストファイルは〇〇_spec.rbとし、specフォルダの中に書きます。
1.ミスするコード
RSpec.describe "A calc" do it "given 2 and 3, return 5" do calc = Calc.new epect(calc.add(2, 3)).to eq(5) end end
[vagrant@localhost rspec]$ rspec F Failures: 1) A calc given 2 and 3, return 5 Failure/Error: calc = Calc.new NameError: uninitialized constant Calc # ./spec/calc_spec.rb:3:in `block (2 levels) in' Finished in 0.00317 seconds (files took 0.32741 seconds to load) 1 example, 1 failure Failed examples: rspec ./spec/calc_spec.rb:2 # A calc given 2 and 3, return 5
2.パスするコードを作成
class Calc def add(a, b) 5 # 仮実装 end end
require 'calc' RSpec.describe "A calc" do it "given 2 and 3, returns 5" do calc = Calc.new expect(calc.add(2, 3)).to eq(5) end end
実行
[vagrant@localhost rspec]$ rspec . Finished in 0.00095 seconds (files took 0.10059 seconds to load) 1 example, 0 failures
flexbox
cssのdisplayをflexとし、幅の比率や順番を簡単に記述することができます。
.container { width: 300px; height: 300px; color: #fff; background: #eee; display: flex; /*flex-direction:column-reverse;*/ /*flex-wrap: wrap;*/ /*flex-wrap: wrap-reverse;*/ /*flex-flow: wrap column;*/ /*justify-content: flex-start;*/ /*justify-content: flex-end;*/ /*justify-content: space-between;*/ /*justify-content: space-around;*/ /*align-items: flex-start;*/ /*align-items: flex-end;*/ /*align-items: flex-center;*/ /*align-items: stretch;*/ /*align-content: flex-start;*/ /*align-content: space-between;*/ /*align-content: space-around;*/ justify-content: center; align-items: center; } .box { width:80px; height: 80px; } /* flex-grow, shrink, basis, margin:auto; */ .box-1 { background: tomato; /*flex: 0 1 120px;*/ /*order: 1; align-self: flex-end;*/} /*.box-2 { background: slategray; /*flex: 0 2 120px;*/ }*/ /*.box-3 { background: pink; margin-left: auto; /*flex: 0 3 120px;*/ }*/
Kotlin 構文2
getter, setter
class User(var name: String){ var team = "red" get(){ return field.toUpperCase() } set(value){ if (value !=""){ field = value } } fun sayHi(){ println("hi $name") } } fun main(args: Array<String>){ val tom = User("tom") println(tom.team) tom.sayHi() }
class override
class AdminUser(name: String): User(name){ fun sayHello(){ println("hello $name") } override fun sayHi(){ println("what $name") } } open class User(var name: String){ open fun sayHi(){ println("hi $name") } } fun main(args: Array<String>){ val bob = AdminUser("bob") println(bob.name) bob.sayHi() }
アクセス修飾子: privateとpublic
open class User(private var name: String){ open fun sayHi(){ println("hi $name") } }
class extension
fun User.sayHello(){ println("hello $name") } val User.myName: String get() = "I am $name" class User(var name: String){ open fun sayHi(){ println("hi $name") } } fun main(args: Array<String>){ val bob = User("bob") bob.sayHello() bob.sayHi() println(bob.myName) }
抽象クラス
abstract class User { abstract fun sayHi() } class Japanese: User(){ override fun sayHi(){ println("こんにちは") } } class American: User(){ override fun sayHi(){ println("hi") } } fun main(args: Array<String>){ val tom = American() val taro = Japanese() tom.sayHi() taro.sayHi() }
interface
interface Sharable{ // 抽象プロパティ、抽象メソッド、メソッド val version: Double fun share() fun getInfo(){ println("Share I/F ($version)") } } class User: Sharable { override val version = 1.1 override fun share(){ println("Sharing..") } } fun main(args: Array<String>){ val user = User() user.share() user.getInfo() }
generics
class MyData<T> { fun getThree(x: T){ println(x) println(x) println(x) } } fun main(args: Array<String>){ val i = MyData<Int>() i.getThree(32) val s = MyData<String>() s.getThree("hello") }
データクラス
data class Point(val x: Int, val y: Int) fun main(args: Array<String>){ val p1 = Point(3, 5) val p2 = Point(3, 5) val p3 = p1.copy() println(p1) println(if (p1 == p2) "same" else "not same") }
List
fun main(args: Array<String>){ val sales: List<Int> = listOf(20, 30, 40) println(sales[1]) println(sales.size) for (sale in sales){ println(sale) } }
set
fun main(args: Array<String>){ val answers: Set<Int> = setOf(3, 5, 8, 3) println(answers) println(answers.contains(3)) val set1 = setOf(1, 3, 5, 8) val set2 = setOf(3, 5, 8, 9) println(set1.intersect(set2)) println(set1.union(set2)) println(set1.subtract(set2)) }
Map
fun main(args: Array<String>){ val users: Map<String, Int> = mapOf("kobayashi" to 10, "kagawa" to 22, "tanaka" to 33) println(users["kobayashi"]) println(users.size) println(users.keys) println(users.values) println(users.entries) }
map, filter, foreach
fun main(args: Array<String>){ val prices = listOf(53.2, 48.2, 32.8) prices /*.map { n -> n + 1.08} //*/ .map { it * 1.08 } .filter { it > 50 } .forEach { println(it) } }
例外処理
fun div(a: Int, b: Int){ try { println(a / b) } catch(e: ArithmeticException) { println(e.message) } } fun main(args: Array<String>){ div(3, 0) }
Nullable型
fun main(args: Array<String>){ val s: String? = null /*println(s)*/ /*if (s != null){ println(s.length) } else { println(null) }*/ println(s?.length ?: -1) }