SlideShare una empresa de Scribd logo
1 de 117
Let’s Go
2015-3-14
송상욱
swsong at fastcatsearch.com
♥ ♥
Why Go?
• 클라우드 시스템 관련 Core들이 Go로 작성되고 있음.
• 특히 Docker는 Go의 성공사례
• 기존 PaaS를 분석하려고 하니 Go를 읽을 줄 알아야한다.
• Github의 Go 프로젝트 59,145개 (2015.3.14기준)
Top Github Projects in Go
• docker/docker
Docker - the open-source application container
engine
• limetext/lime
Open source API-compatible alternative to the
text editor Sublime Text
• syncthing/syncthing
Open Source Continuous File Synchronization
• golang/go
The Go programming language
• GoogleCloudPlatform/kubernetes
Container Cluster Manager from Google
• go-martini/martini
Classy web framework for Go
• joewalnes/websocketd
Turn any program that uses STDIN/STDOUT into a
WebSocket server. Like inetd, but for
WebSockets.
• github/hub
hub helps you win at git.
• coreos/etcd
A highly-available key value store for shared
configuration and service discovery
• astaxie/build-web-application-with-golang
A golang ebook intro how to build a web with
golang
2015.3.14 기준으로 뽑아봤어요
참고문서
• golang-korea
– go 개발언어 관련 자료를 한국어로 번역하는 프로젝트
– https://code.google.com/p/golang-korea/
• 그외의 인터넷 문서들
기초
형아들~♥ 이제 부터 나의 기초를 보여줄게
난 생긴것 처럼 단순한 아이야~ ♥
자 그럼 Let’s Go~♥
Go 는 Object-Oriented 언어인가?
• 맞기도 하고 아니기도 하다.
– http://golang.org/doc/faq#Is_Go_an_object-oriented_language
• 아닌 이유
– 상속관계가 없다. No subclass
• 맞는 이유
– object-oriented 스타일의 프로그래밍을 허용한다. interface제공.
• object-oriented 스타일의 프로그래밍?
– 상속은 제공하지 않으며 interface만 제공.
– implements"라는 선언 필요없음.
– 단순히 해당 인터페이스의 메소드를 구현하기만 하면 인터페이스 사용가능
준비사항
• 홈페이지 : http://golang.org/
• Go SDK 다운로드 : http://golang.org/dl/
• 편집도구 : LiteIDE
– 다운로드 :
http://sourceforge.net/projects/liteide/files/
함수형태
• 리턴값 없음
func f1() { }
• 리턴값 존재
func f1() string {
return “OK”
}
• 리턴값 이름
func f2() (r string) {
r = “OK”
return
}
• struct 내부함수
type Counter struct {
n int
}
func (ctr *Counter) add(int amount) { //리시버 Counter 선언.
ctr.n += amount;
}
func f1() (string, int) {
return “OK”, 1
}
리시버는 나중에 자세하게 나오니까 염려하지마요
Go 가시성
• 최상위 type, 함수, method, 상수, 변수 혹은 구조체의
필드나 method의 이름이 대문자로 시작하면 패키지의
사용자는 접근이 가능
• 반면에 소문자일 경우에는 패키지 내부에서만 접근이
가능
진입점
• main 패키지의 main() 함수
package main
func main() {
//무언가를 수행한다.
}
실행과 빌드
• 실행
$ go run 파일명
• 빌드
$ go build
또는
$ go build 파일명
• 빌드결과삭제
$ go clean
숫자타입
• 정수형
– uint8, uint16, uint32, uint64
– int8, int16, int32, int64
– uint, int, uintptr : 장비의존적
– uint8 == byte
– uint32 == rune
• 부동소숫점
– float32, float64
• 복소수
– complex64, complex128
그외 모든 타입
bool  불린 true, false
numeric  이전 장에서 설명한 숫자타입
string  문자열. Java와 달리 소문자이다.
array  []
slice  [] array를 참조한다. ex) arr[2:5]
struct  ex) type struct Human { }
pointer  *
function  func
interface  interface
map  map
channel  chan
키워드
break default func interface select
case defer go map struct
chan else goto package switch
const fallthrough if range type
continue for import return var
Java와 다른점 몇가지
• 세미콜론은 생략한다. 하지만 같은줄에 여러명령에는 사용.
a= 1
b= 2
c=1; d=2
• 변수선언에는 var를 사용하고 타입은 맨뒤에 선언
var a int cf) int a
var b string cf) String b
• main함수는 파라미터가 없다. 대신 flag사용
var port = flag.String("port", "8080", "Listening port")
func main() {
flag.Parse()
}
• if, for 에 괄호를 사용하지 않으며, 여는 중괄호({)는 반드시 같은줄에 사용한다.
if x > 1 { .. }
for i:=0; i< 100; i++ {
//구현
}
• 선언과 할당을 동시에 할때는 =가 아닌 := 를 사용한다. 이때 변수타입은 값의 타입으로
추정한다.
price := 2000  var price int = 2000 과 동일.
Java와 다른점 몇가지 2
• switch-case 는 break가 필요없다. 기본이 break이며, 필요시 fallthrough 사용.
• try-catch-finally, throw가 없다.
defer  finally
raise  throw
recover  catch
• 포인터존재
var a *Human
a := new(Human)
b := &i
• 사용하지 않는 변수나 import는 컴파일시 에러발생. 제거하거나 주석처리해야한다.
• import 에 alias 를 줄 수 있다.
import “math”
import math2 “my/custom/math”
math2.Average(1,2)
• private , public 이 없다. 대신 함수명이나 변수명이 대문자이면, public이고
소문자이면 private이다.
var Name string  public
var price int  private
func CallMePublic()  public
func callMeInside()  private
Java와 다른점 몇가지 3
• class라는 keyword가 없다. 대신 struct를 만들고 함수에 struct명을
주어(리시버) class와 동일하게 사용할 수 있다.
• Thread가 없다. 대신 light-weight인 고루틴을 사용한다.
go something()  비동기적 something()함수실행
• 여러값을 동시에 리턴가능하다.
return a,b,c
• 여러값을 동시에 할당가능하다.
var a,b,c int = 1,2,3
• 여러변수를 동시에 선언가능하다. import도 동일.
• 자동형변환이 안된다. 명시적 형변환필요.
var c int = 2000
var d float64 = float64(c)  OK. 만약 var d float64 = c 은 에러. var d float64= float32(c))도 에러.
• 배열선업시 괄호는 앞에 쓴다.  []int
var (
a int
b string
)
import (
“fmt”
“io”
)
변수선언/할당
• 사용법1
var x string = "Hello World"
• 사용법2
var x string
x = "Hello World"
• 사용법3
x := "Hello World"
> 일반적으로 많이 사용하는 방식. 타입추정.
변수선언/할당2
• 같은줄에 컴마구분으로 여러변수를 동일 타입으로 정의가능
a int, b int , c int , d int  a, b, c, d int
a int, b int, c float64, d float64  a, b int, c, d float64
func f(a, b int, c, d float64) {
// do something..
}
func main() {
f(1, 2, 3., 4.)
}
다중값 할당
func f() (int, int) {
return 5, 6
}
func main() {
x, y := f()
}
• 오류와 함께 반환하는 기능은 자주 사용됨.
f, err := os.Open(name, os.O_RDONLY, 0)
if err != nil {
return err
}
//파일 f 사용.
다중값 할당2
• 두값의 SWAP이 편하다
• OLD한 방식
a = 10
b = 30
tmp := b
b = a
a = tmp
• Go 방식
a = 10
b= 30
a, b = b, a
• 여러개도 된다.
a, b, c = b, c, a
다중값 할당3
• 동일한 내용 다른 표현
var (
a int = 1
b int = 2
c int = 3
)
var a int, b int, c int = 1, 2, 3
 syntax error: unexpected comma, expecting semicolon or newline or }
var a, b, c int = 1, 2, 3
a, b, c := 1, 2, 3
사용하지 않는 변수
• Go 컴파일러는 사용하지 않는 변수존재시
에러발생.
func main() {
i := 0
}
$ go run test.go
# command-line-arguments
.test.go:16: i declared and not used
문자열 비교
• 자바와 다른점
var x string = "hello"
var y string = "hello"
fmt.Println(x == y)
> true
상수
• 변수
var x string = "Hello World”
• 상수
const x string = "Hello World"
상수
• 상수의 Type을 정하지 않으면, 사용될때context에 의해 정해짐.
const huge = 1 << 100
fmt.Println(huge)  constant 1267650600228229401496703205376 overflows
int
fmt.Println(huge >> 40)  4611686018427387904
• iota(Java의 Enum효과)
const (
red = iota // red == 0
blue // blue == 1
green // green == 2
)
다중 정의
• 변수
var (
a = 5
b = 10
)
• 상수
const (
Space = " ”
Newline = "n"
)
다중 정의
• Import
import (
"os"
"fmt"
)
• Type
type(
book struct {
title string
price int
}
coffee struct {
size int
origin string
}
)
루프
• For가 유일한 루프.
• 괄호가 없다.
– 사용법1
for { }
– 사용법2
for i < 10 { }
– 사용법3
for i:=0 ; i < 10; i++ { }
특별 루프
• Range
func main() {
x := [5]int{1,2,3,4}
for i, value := range x {
fmt.Println(value)
}
}
– i : 현재위치(0부터시작)
– value : 현재값. x[i]
• 컴파일시 에러 : i declared and not used
func main() {
x := [5]int{1,2,3,4}
for _, value := range x {
fmt.Println(value)
}
}
– _(언더스코어)는 컴파일러에게 이것이 필요하지 않다고 알려주는 데 사용
Switch-Case
• 괄호가 없다.
• 상수이거나 Integer이 필요가 없다. 문자열도 가능.
• Break가 필요없다. 기본적으로 break이며, 통과를 원하면 fallthrough.
• switch 값이 생략된 경우에는 기본값은 true가 된다.
func main() {
str := "3"
switch str {
case "1":
fmt.Println("@1")
case "2": fmt.Println("@2")
default :
fmt.Println("default")
}
}
----
switch {
case i < 0 || i > 0:
fmt.Println(”Non-Zero")
fallthrough
case i == 0 : fmt.Println(”Zero")
}
Switch-Case
• 컴마로 여러 조건가능.
switch c {
case ' ', '?', '&', '=', '#', '+', '%':
…
}
배열
• 사용법1
var x [5]int
x[0] = 1; x[1] = 2; ;x[2] = 3; x[3] = 4; x[4] = 5
• 사용법2
x := [5]int{1,2,3,4,5}
• 사용법3
x := [5]int{
1,2,3,4,
5,
}
– 한줄씩 사용할 경우 컴마가 반드시 값뒤에 붙어야하고, 마지막 원소도
반드시 컴마존재.
• 사용법4
x := []int{1,2,3,4,5,7,8,9,10} // [1,2,3,4,5,7,8,9,10]
또는 x := []int{} // []
– 배열의 길이를 정하지 않아도 됨.
슬라이스
• 배열을 참조하는 일부를 가리킴.데이터공유
arr := []int{1,2,3,4,5}
x := arr[0:3] // 0<=i<3  [1,2,3]
x := arr[:3] // i<3  [0:3]과 동일
x := arr[3:] // i >= 3  [4,5]
• 선언
var x []float64
• 생성
x := make([]float64, 5)
x := make([]float64, 5, 10)
슬라이스
• 배열을 참조하는 일부를 가리킴.데이터공유
arr := []int{1,2,3,4,5}
x := arr[0:3] // 0<=i<3  [1,2,3]
x := arr[:3] // i<3  [0:3]과 동일
x := arr[3:] // i >= 3  [4,5]
• 선언
var x []float64
• 생성
x := make([]float64, 5)
x := make([]float64, 5, 10)
슬라이스 관련함수
• append
slice1 := []int{1,2,3}
slice2 := append(slice1, 4, 5) // 4,5 를 추가.
// slice1  [1,2,3]
// slice2  [1,2,3,4,5]
• copy
slice1 := []int{1,2,3}
slice2 := make([]int, 2) // 길이가 2인 슬라이스
copy(slice2, slice1)
// slice1  [1,2,3]
// slice2  [1,2]
맵
• Key는 동등연산자(==)이 가능한 integer, float, 복소수, string,
포인터, 그리고 인터페이스와 같이 어떤 타입이든 가능
• struct와 배열,slice는 동등연산을 할 수 없기 때문에 불가.
• 사용법1
var x map[string]int
x = make(map[string]int)
x["a"]=1; x["b"]=2; x["c"]=3
• 사용법2
x := make(map[string]int)
x["a"]=1; x["b"]=2; x["c"]=3
• 사용법3
x := map[string]int{"a":1, "b":2, "c":3}
맵
• 참조
name := x[”aaaa"]
또는
name, ok := x[”aaaa"]
fmt.Println(name, ok)
• 삭제
delete(x, "b")
• 갯수확인
len(x)
다중맵
elements := map[string]map[string]string{
"H": map[string]string{
"name":"Hydrogen",
"state":"gas",
},
"He": map[string]string{
"name":"Helium",
"state":"gas",
},
}
가변함수
func add(args ...int) int {
total := 0
for _, v := range args {
total += v
}
return total
}
• add(1,2,3)  OK
• xs := []int{1,2,3}
add(xs)  Error. 가변인자는 슬라이스와 호환되지 않는다.
• add(xs...)  OK. 가변인자 변수자체를 전달할때는 ...을 붙여야 인식됨.
가변인자는 add(foo...)와 같이 ...를 반드시 붙어야해요
클로저
func main() {
add := func(x, y int) int {
return x + y
}
fmt.Println(add(1,1))
}
---------------------------------------------------------------------------------------------
func makeEvenGenerator() func() uint {
i := uint(0)
return func() (ret uint) {
ret = i
i += 2
return
}
}
func main() {
nextEven := makeEvenGenerator()
fmt.Println(nextEven()) // 0
fmt.Println(nextEven()) // 2
fmt.Println(nextEven()) // 4
}
Defer (지연된 호출)
• 해당함수 종료시 실행됨.
• Java의 try-finally 대체
func main() {
defer second()
first()
}
------------------------------------------------
f, _ := os.Open(filename)
defer f.Close()
• 장점
1. Close 호출을 Open 호출 가까이에 둬서 이해하기가 쉽다.
2. 함수에 return이 여러 개 있더라도 Close가 어떠한 return 시라도 호출
3. 지연된 함수는 런타임 패닉이 일어나더라도 실행
Panic & Recover
• Java의 throw-catch 를 대체
• panic : 런타임오류 강제발생
• recover : 런타임패닉 처리
• 잘못된 사용예. recover가 호출기도 전에 종료.
panic("PANIC")
str := recover()
• 올바른 사용예. defer와 짝을 맞춤. 익명함수 사용.
defer func() {
str := recover()
fmt.Println(str)
}()
panic("PANIC”)
• 사용목적
– 범위를 벗어난 배열 인덱스에 접근시 에러처리
– 맵을 초기화하는 것을 잊어버릴 경우 에러처리
구조체 / 인터페이스
포인터
• Address 연산자로 포인터 사용
func one(xPtr *int) {
*xPtr = 0
}
func main() {
x := 5
one(&x)
fmt.Println(x) // x는 1
}
----------------------------
• new 로 포인터 사용
func main() {
xPtr := new(int)
one(xPtr)
fmt.Println(*xPtr) // x는 1
}
포인터 접근
type Rectangle struct {
length, width int
}
func main() {
var r *Rectangle
r = new(Rectangle) // Rectangle에 대한 포인터 반환.
r.length = 5
(*r).length = 5 //r.length=5와 동일하다.
fmt.Println(r.length) //  5
fmt.Println((*r).length) //  5
}
• c++과 달리 -> 가 없다. 포인터, 인스턴스 모두에 대해 dot(.) 노테이션 사용
Struct
• Go는 클래스가 없다.
• 하지만 클래스와 동일한걸 만들수 있다.
• Java에서 Rectangle 클래스는 area()메소드를 가지고 있음
//JAVA
public class Rectangle {
private float x1, y2, x2, y2;
public float area() {
float l = distance(x1, y1, x1, y2);
float w = distance(x1, y1, x2, y1);
return l * w;
}
private float distance(float x1, float y1, float x2, float y2) {
float a = x2 - x1;
float b = y2 - xy;
return Math.sqrt(a*a + b*b);
}
}
Struct
//C++
class rectangle {
private:
float x1, y2, x2, y2;
public:
float area(void);
}
inline float rectangle::area()
{
float l = distance(x1, y1, x1, y2);
float w = distance(x1, y1, x2, y1);
return l * w;
}
float distance(float x1, float y1, float x2, float y2)
{
float a = x2 - x1;
float b = y2 - xy;
return sqrt(a*a + b*b);
}
Struct
• Receiver를 사용하여 특정 type에 종속적 함수를 생성한다.
//Go
type Rectangle struct {
x1, y1, x2, y2 float64
}
func (r *Rectangle) area() float64 {
l := distance(r.x1, r.y1, r.x1, r.y2)
w := distance(r.x1, r.y1, r.x2, r.y1)
return l * w
}
func distance(x1, y1, x2, y2 float64) float64 {
a := x2 – x1
b := y2 – y1
return math.Sqrt(a*a + b*b)
}
func main() {
r := Rectangle{1, 5, 3, 7}
fmt.Println(r) //  {1 5 3 7}
}
Struct
• 리시버는 포인터 or 객체중 어느걸 써야할까?
type Rectangle struct {
length, width int
}
func (r Rectangle) set(i, j int) {
r.length = i
r.width = j
}
-----
• Receiver는 아래 두가지 모두 사용가능.
func (r Rectangle) set(i, j int) { .. } // OK
func (r *Rectangle) set(i, j int) { .. } // OK
Struct
1. 객체 사용시
func (r Rectangle) set(i, j int) {
r.length = i
r.width = j
}
func main() {
r := Rectangle{1, 5}
r.set(10, 50)
fmt.Println(r) //  [1 5] 안바뀐다. r이 set함수에 복사되어 전달됨. shallow copy.
}
2. 포인터 사용시
func (r *Rectangle) set(i, j int) { ..}
결과 [10 50]
변경됨. call by reference.
Struct
• 생성방식
type Rectangle struct {
length, width int
}
var r Rectangle // Rectangle타입. 내용은 length=0, width=0
var r *Rectangle // *Rectangle타입. 내용은 nil.
r := new(Rectangle) // *Rectangle타입. 내용은 length=0, width=0
r := Rectangle{width:10, length: 50} // Rectangle타입. 이름명시
r := Rectangle{10, 50} // Rectangle타입. 순서대로 할당
Struct – embedded type
type Person struct {
Name string
}
• HAS-A 관계
type Android struct {
Person person
Model string
}
a.person.Name=5 //Person을 통해서 접근
• IS-A 관계
type Android struct {
Person //Android is a person
Model string
}
a := new(Android)
a.Name=5 // Android가 Person인것 처럼 접근가능.
Struct –기본 타입 확장
• 기존 int 타입을 기반으로 string() 함수를 붙인다.
#src/fmt/stringer_test.go 참조
type TI int
func (v TI) String() string {
return fmt.Sprintf("I: %d", int(v))
}
• Java라면
public class IntegerType extends Integer {
public String string() { .. }
}
$ javac IntegerType.java
IntegerType.java:1: error: cannot inherit from final Integer
public class IntegerType extends Integer {
^
1 error
 Integer는 Final class 이므로 확장 불가.
Interface
• Rectangle
type Rectangle struct {
x1, y1, x2, y2 float64
}
func (r *Rectangle) area() float64 { .. }
• Circle
type Circle struct {
x, y, r float64
}
func (c *Circle) area() float64 { .. }
• Shape
type Shape interface {
area() float64
}
• 사용시
func totalArea(shapes ...Shape) float64 { .. }
어떠한 선언적 종속관계도 없다!!
동시성
고루틴(go)
package main
import (
"fmt"
"math/rand"
"time"
)
func f(n int) {
amt := time.Duration(rand.Intn(250))
time.Sleep(time.Millisecond * amt)
fmt.Println(n)
}
func main() {
for i := 0; i < 1000000; i++ {
go f(i)
}
var input string
fmt.Scanln(&input)
}
채널(chan)
• 채널(channel)은 두 고루틴이 서로 통신하고 실행흐름을 동기화하는 수단을
제공
func main() {
c := make(chan string)
c <- "oce”
msg := <-c
fmt.Println(msg)
}
결과
$ go run main.go
fatal error: all goroutines are asleep - deadlock!
• main함수는 첫번째 고루틴이다.
채널(chan)
func main() {
c := make(chan string)
go func() { // 익명 함수의 고루틴
c <- "oce”
}()
msg := <-c
fmt.Println(msg)
}
결과
$ go run main.go
oce
• 비동기 채널설정
기본적으로 채널은 동기적. 버퍼를 주면 비동기적으로 동작가능.
c := make(chan int, 1) //길이가 1인 버퍼설정.
채널(chan) - 방향
• 양방향
func f(c chan string)
• 입력전용
func f(c chan<- string)
• 출력전용
func f(c <-chan string)
Select
c1 := make(chan string)
c2 := make(chan string)
select {
case msg1 := <- c1:
fmt.Println("Message 1", msg1)
case msg2 := <- c2:
fmt.Println("Message 2", msg2)
case <- time.After(time.Second):
fmt.Println("timeout")
default:
fmt.Println("nothing ready")
}
기타
초기화
• func init() 이 존재하면 main()보다도 먼저실행
• init()은 해당패키지 import시 실행
– import “abc” 가 실행시 abc.go내 init()이 실행된다.
• init() 여러번 중복해서 선언될수 있으며, 코드 순서대로 순차적 실행
package main
import "fmt”
var i = foo()
func foo() int {
fmt.Println("Call foo()")
return 1
}
func init() {
fmt.Println("Call init() 1")
}
func init() {
fmt.Println("Call init() 2")
}
func main() {
fmt.Println("Call main()")
}
func init() {
fmt.Println("Call init() 3")
}
실행결과
Call foo()
Call init() 1
Call init() 2
Call init() 3
Call main()
make()와 new()의 차이
• make()
– 오로지 slice, map, channel을 만드는 용도로만 사용.
– 포인터를 반환하지 않음. 즉 *T가 아닌 T타입을 리턴.
var p *[]int = new([]int) // slice구조를 할당함; *p == nil; 그다지 유용하지 않음
var v []int = make([]int, 100) // slice v는 이제 100개의 int를 가지는 새로운 배열을 참조함
// new : 불필요하게 복잡함:
var p *[]int = new([]int)
*p = make([]int, 100, 100)
// make: 자연스러움:
v := make([]int, 100)
Conversion
var f1 float64 = 6.0
f2 := 12 / f1 // 상수 12는 float64로 자동변환
 2
var i int = 12
var f1 float64 = 6.0
f2 := i / f1 // 변수타입은 자동변환되지 않는다.
 invalid operation: i / f1 (mismatched types int and float64)
var i = 12. //12. 은 float64 형이다.
var f1 float32 = 6.0
f2 := i / f1 //심지어 같은 float형이라도 float32와 float64는 자동형변환
불가.
 invalid operation: i / f1 (mismatched types float64 and float32)
Conversion
var i = 12.
var f1 float32 = 6.0
f2 := i / f1
 ERROR
var i = 12.
var f1 float32 = 6.0
f2 := float32(i) / f1
 2
i := 12
fmt.Println(”Result = ” + i)
 cannot convert "Result=" to type int
invalid operation: "Result=" + i (mismatched types string and int)
import ”strconv”
i := 12
fmt.Println("Result = " + strconv.Itoa(i))
 Result = 3
GOROOT
• GOROOT는 Go SDK의 설치위치를 나타내며, 이 위치하위에서 기본
라이브러리와 문서등을 찾아서 사용한다.
• Go 기본설치위치
– *nix : /usr/local/go
– Windows : C:Go
• 만약 다른 곳에 설치했다면 GOROOT 환경변수를 설정해주어야함.
– ex) /application/go에 설치했다면,
export GOROOT=/application/go
export PATH=$PATH:$GOROOT/bin
– *nix계열은 .bash_profile과 같은 설정파일에 추가한다.
• 기본위치에 설치되어 있다면 GOROOT를 설정할 필요없음
GOPATH
• Java에는 classpath, Go에는 GOPATH
• import 시 GOPATH의 경로를 찾음
• *Nix계열은 콜론, Windows는 세미콜론으로 연결된 경로 리스트
GOPATH=/home/user/gocode
/home/user/gocode/
src/
foo/
bar/ (go code in package bar)
x.go
grep2/ (go code in package main)
y.go
bin/
grep2 (installed command)
pkg/
linux_amd64/
oce/
bar.a (installed package object)
Tip: GOPATH가 여러개일때 특정 src하위에서 install 된 패키지파일은 해당 고패스하위로 들어간다.
패키지
GOPATH=<User Home Directory>/go
$ cd go
$ mkdir -p src/math2
$ cd src/math2
$ vi foo.go # 파일명과 패키지 명이 동일할 필요없음.
package math2 // 패키지명은 폴더와 이름이 일치해야함.
func Average(i, j int) float64 { // average가 아닌 대문자 Average로 선언. import후 호출가능함
return float64(i + j) / 2
}
$ go install
 <User Home Directory>/go/pkg/darwin_amd64/math2.a 생성됨.
-------------------
package main
import “fmt”
import “math2”
func main() {
i := math2.Average(10,30) // 20
fmt.Println(“i=“, i)
}
> 패키지명을 math로 하면 이미 존재하는 go의 기본패키지명과 겹치므로 go install시 에러발생.
패키지
• 최상위가 아닌 중간경로를 주면 math라는 이름으로 패키지 생성가능.
$ mkdir -p src/oce.org/math
$ cd src/oce.org/math
$ vi foo.go
package math
func Average(i, j int) float64 {
return float64(i + j) / 2
}
$ go install
 <User Home Directory>/go/pkg/darwin_amd64/oce.org/math.a 생성됨.
-------------------
package main
import “fmt”
import “oce.org/math”
func main() {
i := math.Average(10,30) // 20
fmt.Println(“i=“, i)
}
패키지
• 패키지 이름의 중복을 방지하기 위하여 import시 Alias가능
package main
import “fmt”
import “math”
import math2 “oce.org/math”
func main() {
i := math.Average(10,30)
j := math2.Average(10,30)
fmt.Println(“i=“, i, “j=“, j)
}
패키지
• Alias를 Dot(.) 으로 하면 해당패키지를 이름없이 바로 접근가능.
package main
import . “fmt”
func main() {
Println(“Called without package name!”)
}
패키지 - remote
• go get
문서화
• Java에는 javadoc, Go에는 godoc
• usage: godoc package [name ...]
godoc -http=:6060
$ godoc oce.org/math
PACKAGE DOCUMENTATION
package math
import "oce.org/math”
FUNCTIONS
func Average(i, j int) float64
$ godoc oce.org/math average  대소문자구분
No match found.
$ godoc oce.org/math Average
func Average(i, j int) float64
$godoc –http=:6060  로컬 웹서버시작
 http://localhost:6060/pkg/
문서화
//Copyright 2015
// oce.org에서 제공하는 수학패키지.
//  빈줄삽입.
// 2015-3-14 업데이트.
package math
// 평균을 구한다.
// 입력값은 i,j 정수를 받아들인다.
// 리턴값은 float64이다.
//
// 입력값:
// i 첫번째정수  Tab을 넣었다.
// j 두번째정수  Tab을 넣었다.
func Average(i, j int) float64 {
return float64(i + j) / 2
}
주석에 Tab이 들어있으면, 회색Box안으로 표시되요
문서화
$ go install; godoc oce.org/math
PACKAGE DOCUMENTATION
package math
import "oce.org/math"
oce.org에서 제공하는 수학패키지.
 빈줄이 나타났다.
2015-3-14 업데이트.
FUNCTIONS
func Average(i, j int) float64
평균을 구한다. 입력값은 i,j 정수를 받아들인다. 리턴값은 float64이다.  주석내 개행은
무시된다.
입력값:
i 첫번째정수
j 두번째정수
문서화
http://localhost:6060/pkg
$ godoc -http=:6060
문서화
http://localhost:6060/pkg/oce.org/math/$ godoc -http=:6060
가장 좋은 문서화예제는 Go
sdk의 소스에 있어요.
<GOROOT>/src/fmt/print.go
<GOROOT>/src/fmt/doc.go
를 참조하세요.
문서화
• Example 도 넣을수 있다.
패키지 os/exec/
문서화
• 함수정의 (src/os/exec/exec.go, src/os/exec/lp_unix.go)
func LookPath(file string) (string, error) { .. }
func (c *Cmd) Start() error { .. }
• 예제정의(src/os/exec/example_test.go)
func ExampleLookPath() {
path, err := exec.LookPath("fortune")
if err != nil {
log.Fatal("installing fortune is in your future")  이 소스가 예제항목으로 삽입된다.
}
fmt.Printf("fortune is available at %sn", path)
}
func ExampleCmd_Start() {
cmd := exec.Command("sleep", "5")
err := cmd.Start()
if err != nil {
log.Fatal(err)  이 소스가 예제항목으로 삽입된다.
}
log.Printf("Waiting for command to finish...")
err = cmd.Wait()
log.Printf("Command finished with error: %v", err)
}
테스트
• 테스트 함수만드는 법
– 파일이름은 _test.go로 끝난다.
– 함수이름이 Test로 시작
– *testing.T를 인자로 받을것 (import “testing”)
• 예제
# foo_test.go
package math
import "testing"
func TestAverage(t *testing.T) {
var v float64
v = Average([]float64{1,2})
if v != 1.5 {
t.Error("Expected 1.5, got ", v)
}
}
테스트
$ go test
PASS
ok oce.org/math 0.003s
• 만약 파일명이 _test.go, test.go, foo_testing.go 등 파일명규칙을 따르지 않을때는
아래와 같이 테스트파일을 못찾는다.
$ go test
? oce.org/math [no test files]
• fmt 패키지내 파일 리스트 참고 (경로 <GOROOT>/src/fmt)
doc.go
export_test.go
fmt_test.go
format.go
print.go
scan.go
scan_test.go
stringer_test.go
테스트
import "testing"
type testpair struct {
values []float64
average float64
}
var tests = []testpair{
{ []float64{1,2}, 1.5 },
{ []float64{1,1,1,1,1,1}, 1 },
{ []float64{-1,1}, 0 },
}
func TestAverage(t *testing.T) {
for _, pair := range tests {
v := Average(pair.values)
if v != pair.average {
t.Error(
"For", pair.values,
"expected", pair.average,
"got", v,
)
}
}
}
struct를 이용하면 여러
테스트값을 편하게
테스트해볼 수 있어요.
핵심패키지
strings
strings.Contains("test", "es") // true
strings.Count("test", "t") // 2
strings.HasPrefix("test", "te") // true
strings.HasSuffix("test", "st") // true
strings.Index("test", "e") // 1
strings.Join([]string{"a","b"}, "-") // "a-b"
strings.Repeat("a", 5) // "aaaaa"
strings.Replace("aaaa", "a", "b", 2) // "bbaa"
strings.Split("a-b-c-d-e", "-") // []string{"a","b","c","d","e"}
strings.ToLower("TEST") // "test"
strings.ToUpper("test") // "TEST”
----
arr := []byte("test")
str := string([]byte{'t','e','s','t'})
더 많은 정보는 여기있어요
https://golang.org/pkg/strings
io
• 함수정의 보다는 대부분이 interface로 구성
• 주요 인터페이스는 Reader와 Writer
• Reader는 Read(), Writer는 Write() 지원
• Reader  Writer 데이터 복사
– func Copy(dst Writer, src Reader) (written int64, err error)
더 많은 정보는 여기있어요
https://golang.org/pkg/io
bytes
package main
import (
"bytes"
"fmt"
"os"
)
func main() {
var b bytes.Buffer // 버퍼는 초기화가 필요없다. 선언후 그대로 사용.
b.Write([]byte("Hello "))
fmt.Fprintf(&b, "world!")
b.WriteTo(os.Stdout)
}
-----
func main() {
// string 이나 []byte 를 io.Reader 로 바꿔준다.
buf := bytes.NewBufferString("R29waGVycyBydWxlIQ==")
dec := base64.NewDecoder(base64.StdEncoding, buf)
io.Copy(os.Stdout, dec)
}
더 많은 정보는 여기있어요
https://golang.org/pkg/bytes
os
• 파일열기 : os.Open()
• 파일닫기 : file.Close()
package main
import (
"fmt"
"os"
)
func main() {
file, err := os.Open("test.txt")
if err != nil {
// 오류를 처리
return
}
defer file.Close()
// 파일의 크기를 구함
stat, err := file.Stat()
if err != nil {
return
}
// 파일을 읽음
bs := make([]byte, stat.Size())
_, err = file.Read(bs)
if err != nil {
return
}
str := string(bs)
fmt.Println(str)
}
error
• 오류에 대한 내장타입
• error.New() 사용시 자체오류 생성가능
package main
import (
"errors"
"fmt"
)
func main() {
err := errors.New("emit macho dwarf: elf header corrupted")
if err != nil {
fmt.Print(err)
}
}
-----
func main() {
const name, id = "bimmler", 17
err := fmt.Errorf("user %q (id %d) not found", name, id)
if err != nil {
fmt.Print(err)
}
}
container
heap Package heap provides heap operations for any type that implements heap.Interface.
list Package list implements a doubly linked list.
ring Package ring implements operations on circular lists.
package main
import (
"container/list"
"fmt"
)
func main() {
// Create a new list and put some numbers in it.
l := list.New()
e4 := l.PushBack(4)
e1 := l.PushFront(1)
l.InsertBefore(3, e4)
l.InsertAfter(2, e1)
// Iterate through list and print its contents.
for e := l.Front(); e != nil; e = e.Next() {
fmt.Println(e.Value)
}
}
container - heap
// This example demonstrates an integer heap built using
the heap interface.
package main
import (
"container/heap"
"fmt"
)
// An IntHeap is a min-heap of ints.
type IntHeap []int
func (h IntHeap) Len() int { return len(h) }
func (h IntHeap) Less(i, j int) bool { return h[i] < h[j] }
func (h IntHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
func (h *IntHeap) Push(x interface{}) {
// Push and Pop use pointer receivers because
they modify the slice's length,
// not just its contents.
*h = append(*h, x.(int))
}
func (h *IntHeap) Pop() interface{} {
old := *h
n := len(old)
x := old[n-1]
*h = old[0 : n-1]
return x
}
// This example inserts several ints into an
IntHeap, checks the minimum,
// and removes them in order of priority.
func main() {
h := &IntHeap{2, 1, 5}
heap.Init(h)
heap.Push(h, 3)
fmt.Printf("minimum: %dn", (*h)[0])
for h.Len() > 0 {
fmt.Printf("%d ", heap.Pop(h))
}
}
sort
• Sort 함수는 sort.Interface가 구현된 것만 정렬가능
• sort.Interface는 Len, Less, Swap의 3개 메서드 필요.
type Interface interface {
// Len is the number of elements in the collection.
Len() int
// Less reports whether the element with
// index i should sort before the element with index j.
Less(i, j int) bool
// Swap swaps the elements with indexes i and j.
Swap(i, j int)
}
sort
type Person struct {
Name string
Age int
}
type ByName []Person
func (this ByName) Len() int {
return len(this)
}
func (this ByName) Less(i, j int) bool {
return this[i].Name < this[j].Name
}
func (this ByName) Swap(i, j int) {
this[i], this[j] = this[j], this[i]
}
func main() {
kids := []Person{
{"Jill",9},
{"Jack",10},
}
sort.Sort(ByName(kids))
fmt.Println(kids)
}
hash
type Hash interface {
// Write (via the embedded io.Writer interface) adds more data
to the running hash.
// It never returns an error.
io.Writer
// Sum appends the current hash to b and returns the resulting
slice.
// It does not change the underlying hash state.
Sum(b []byte) []byte
// Reset resets the Hash to its initial state.
Reset()
// Size returns the number of bytes Sum will return.
Size() int
// BlockSize returns the hash's underlying block size.
// The Write method must be able to accept any amount
// of data, but it may operate more efficiently if all writes
// are a multiple of the block size.
BlockSize() int
}
type Hash32 interface {
Hash
Sum32() uint32
}
type Hash64 interface {
Hash
Sum64() uint64
}
hash - 비암호화
• 종류 : adler32, crc32, crc64, fnv
package main
import (
"fmt"
"hash/crc32"
)
func main() {
h := crc32.NewIEEE()
h.Write([]byte("test"))
v := h.Sum32()
fmt.Println(v)
}
 3632233996
crypto – 암호화해시
• 종류 : aes, cipher, des, dsa, ecdsa, elliptic, hmac, md5, rand, rc4, rsa, sha1,
sha256, sha512, subtle, tls, 509
package main
import (
"crypto/sha1"
"fmt"
"io"
)
func main() {
h := sha1.New()
io.WriteString(h, "His money is twice tainted:")
io.WriteString(h, " 'taint yours and 'taint mine.")
fmt.Printf("% x", h.Sum(nil))
}
net
• Go는 아래에 대해 Portable 인터페이스를 제공
– Network I/O
– TCP/IP
– UDP
– Domain name resolution
– Unix domain socket
type Listener interface {
// Accept waits for and returns the next connection to the listener.
Accept() (c Conn, err error)
// Close closes the listener.
// Any blocked Accept operations will be unblocked and return errors.
Close() error
// Addr returns the listener's network address.
Addr() Addr
}
net
//////////////////// Client 간단버전 //////////////////
conn, err := net.Dial("tcp", "google.com:80")
if err != nil {
// handle error
}
fmt.Fprintf(conn, "GET / HTTP/1.0rnrn")
status, err := bufio.NewReader(conn).ReadString('n')
// ...
////////////////// Server 간단버전 //////////////////
ln, err := net.Listen("tcp", ":8080")
if err != nil {
// handle error
}
for {
conn, err := ln.Accept()
if err != nil {
// handle error
}
go handleConnection(conn)
}
net
////////////// Echo 서버 ////////////
package main
import (
"io”; "log”; "net"
)
func main() {
// Listen on TCP port 2000 on all interfaces.
l, err := net.Listen("tcp", ":2000")
if err != nil {
log.Fatal(err)
}
defer l.Close()
for {
// Wait for a connection.
conn, err := l.Accept()
if err != nil {
log.Fatal(err)
}
// Handle the connection in a new
goroutine.
// The loop then returns to accepting, s
o that
// multiple connections may be served
concurrently.
go func(c net.Conn) {
// Echo all incoming data.
io.Copy(c, c)
// Shut down the connection.
c.Close()
}(conn)
}
}
$ telnet localhost 2000
I love Go  입력
I love Go  출력
net/http
package main
import ("net/http" ; "io")
func hello(res http.ResponseWriter, req
*http.Request) {
res.Header().Set(
"Content-Type",
"text/html",
)
io.WriteString(
res,
`<doctype html>
<html>
<head><title>Hello World</title></head>
<body>Hello World!</body>
</html>`,
)
}
func main() {
http.HandleFunc("/hello", hello)
http.ListenAndServe(":9000", nil)
}
http://localhost:9000/hello
HandleFunc는 URL 라우팅(/hello)
처리를 담당해요
net/rpc
package main
import (
"fmt” ; "net”; "net/rpc"
)
type Server struct {}
func (this *Server) Negate(i int64, reply *int64) error {
*reply = -i
return nil
}
func server() {
rpc.Register(new(Server))
ln, err := net.Listen("tcp", ":9999")
if err != nil {
fmt.Println(err)
return
}
for {
c, err := ln.Accept()
if err != nil {
continue
}
go rpc.ServeConn(c)
}
}
func client() {
c, err := rpc.Dial("tcp", "127.0.0.1:9999")
if err != nil {
fmt.Println(err)
return
}
var result int64
err = c.Call("Server.Negate", int64(999), &result)
if err != nil {
fmt.Println(err)
} else {
fmt.Println("Server.Negate(999) =", result)
}
}
func main() {
go server()
go client()
var input string
fmt.Scanln(&input)
}
flag (명령줄 파싱)
• 명령줄 플래그(-로 시작)를 flag.String(), Bool(), Int() 등을 사용하여 파싱
– flag.Int(플래그명, 기본값, 설명메시지)
– flag.IntVar(입력변수주소, 플래그명, 기본값, 설명메시지)
– 방법1
import "flag"
var ip = flag.Int("flagname", 1234, "help message for flagname”)
– 방법2
var flagvar int
func init() {
flag.IntVar(&flagvar, "flagname", 1234, "help message for flagname")
}
• 플래그가 아닌 일반파라미터는 flag.Args()를 통해 받을 수 있으며
[]string 형으로 리턴된다.
var args []string = flag.Args()
flag (명령줄 파싱)
package main
import (
"flag"
"fmt"
)
var species = flag.String("species", "gopher", "the species we are studying")
var gopherType string
func init() {
const (
defaultGopher = "pocket"
usage = "the variety of gopher"
)
flag.StringVar(&gopherType, "gopher_type", defaultGopher, usage)
flag.StringVar(&gopherType, "g", defaultGopher, usage+" (shorthand)")
}
func main() {
flag.Parse()
fmt.Println("species=", *species, "ngopherType=", gopherType)
var args []string = flag.Args()
fmt.Println("Args=", args)
}
flag (명령줄 파싱)
$ ./hello
species= gopher
gopherType= pocket
Args= []
$ ./hello -h
Usage of ./hello:
-g="pocket": the variety of gopher (shorthand)
-gopher_type="pocket": the variety of gopher
-species="gopher": the species we are studying
$ ./hello -species=oce -g=fastcat
species= oce
gopherType= fastcat
Args= []
$ ./hello -species=oce -gopher_type=fastcat  위 결과와 동일
species= oce
gopherType= fastcat
Args= []
$ ./hello -species=”oce fastcat” world war 2
species= oce fastcat
gopherType= pocket
Args= [world war 2]
sync
type Cond
func NewCond(l Locker) *Cond
func (c *Cond) Broadcast()
func (c *Cond) Signal()
func (c *Cond) Wait()
type Locker
type Mutex
func (m *Mutex) Lock()
func (m *Mutex) Unlock()
type Once
func (o *Once) Do(f func())
type Pool
func (p *Pool) Get() interface{}
func (p *Pool) Put(x interface{})
type RWMutex
func (rw *RWMutex) Lock()
func (rw *RWMutex) RLock()
func (rw *RWMutex) RLocker() Locker
func (rw *RWMutex) RUnlock()
func (rw *RWMutex) Unlock()
type WaitGroup
func (wg *WaitGroup) Add(delta int)
func (wg *WaitGroup) Done()
func (wg *WaitGroup) Wait()
더 많은 정보는 여기있어요
https://golang.org/pkg/sync/
sync/Mutex
package main
import (
"fmt”; "sync”; "time"
)
func main() {
m := new(sync.Mutex)
for i := 0; i < 10; i++ {
go func(i int) {
m.Lock()
fmt.Println(i, "start")
time.Sleep(time.Second)
fmt.Println(i, "end")
m.Unlock()
}(i)
}
var input string
fmt.Scanln(&input)
}
실행결과
0 start
0 end
1 start
1 end
2 start
2 end
3 start
3 end
4 start
4 end
5 start
5 end
6 start
6 end
7 start
7 end
8 start
8 end
9 start
9 end
sync/Once
package main
import (
"fmt”; "sync"
)
func main() {
var once sync.Once
onceBody := func() {
fmt.Println("Only once")
}
done := make(chan bool)
for i := 0; i < 10; i++ {
go func() {
once.Do(onceBody)
done <- true
}()
}
for i := 0; i < 10; i++ {
<-done
}
}
 결과 : Only once
sync/WaitGroup
var wg sync.WaitGroup
var urls = []string{
"http://www.golang.org/",
"http://www.google.com/",
"http://www.somestupidname.com/",
}
for _, url := range urls {
// Increment the WaitGroup counter.
wg.Add(1)
// Launch a goroutine to fetch the URL.
go func(url string) {
// Decrement the counter when the goroutine completes.
defer wg.Done()
// Fetch the URL.
http.Get(url)
}(url)
}
// Wait for all HTTP fetches to complete.
wg.Wait()
Go 의 동기화 스타일
type Work struct {
x, y, z int
assigned, done bool
}
type WorkSet struct {
mu sync.Mutex
work []*Work
}
type Work struct { x, y, z int }
func worker(in <-chan *Work, out chan<- *Work) {
for w := range in {
w.z = w.x * w.y // do some work...
out <- w
}
}
func main() {
in, out := make(chan *Work), make(chan *Work)
for i := 0; i < 10; i++ { go worker(in, out) }
go sendLotsOfWork(in)
receiveLotsOfResults(out)
}
메모리공유를 통한 통신이나
공유데이터를 보호하기 위한 Lock이 필요없다.
전통적인 접근 Go 스타일
time
정의 : func Sleep(d Duration)
샘플 : time.Sleep(100 * time.Millisecond)
정의 : func (t Time) Sub(u Time) Duration
샘플 :
t0 := time.Now()
expensiveCall()
t1 := time.Now()
mt.Printf("The call took %v to run.n", t1.Sub(t0))
 3m56s
정의 : func Date(year int, month Month, day, hour, min, sec, nsec int, loc *Location) Time
샘플 : t := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)
정의 : func (t Time) Format(layout string) string
샘플 :
const layout = "Jan 2, 2006 at 3:04pm (MST)"
t := time.Date(2009, time.November, 10, 15, 0, 0, 0, time.Local)
fmt.Println(t.Format(layout))
정의 : func Parse(layout, value string) (Time, error)
샘플 :
const longForm = "Jan 2, 2006 at 3:04pm (MST)"
t, _ := time.Parse(longForm, "Feb 3, 2013 at 7:54pm (PST)")
Go 에는 Java의 yyyyMMdd
같은 형식이 없어요.
regexp
정의 : func MatchString(pattern string, s string) (matched bool, err error)
샘플 : matched, err := regexp.MatchString("foo.*", "seafood")
정의 : func MustCompile(str string) *Regexp
샘플 : var re = regexp.MustCompile(`^[a-z]+[[0-9]+]$`)
정의 : func (re *Regexp) MatchString(s string) bool
샘플 : fmt.Println(re.MatchString("adam[23]"))
정의 : func (re *Regexp) FindAllString(s string, n int) []string
샘플 : fmt.Println(re.FindAllString("paranormal", -1))
정의 : func (re *Regexp) ReplaceAllString(src, repl string) string
샘플 : fmt.Println(re.ReplaceAllString("-ab-axxb-", "T"))
database
age := 27
rows, err := db.Query("SELECT name FROM users WHERE age=?", age)
if err != nil {
log.Fatal(err)
}
defer rows.Close()
for rows.Next() {
var name string
if err := rows.Scan(&name); err != nil {
log.Fatal(err)
}
fmt.Printf("%s is %dn", name, age)
}
if err := rows.Err(); err != nil {
log.Fatal(err)
}
https://github.com/golang/go/wiki/SQLDrivers
database - drivers
• MySQL: https://github.com/ziutek/mymysql [*]
• MySQL: https://github.com/go-sql-driver/mysql/ [*]
• Postgres (pure Go): https://github.com/lib/pq [*]
• Oracle: https://github.com/mattn/go-oci8
• MS SQL Server (pure go): https://github.com/denisenkom/go-mssqldb
그 외의 드라이버는 여기를 참조하세요.
https://github.com/golang/go/wiki/SQLDrivers
database - mysql
package main
import (
"os"
"github.com/ziutek/mymysql/mysql"
_ "github.com/ziutek/mymysql/native" // Native
engine
// _ "github.com/ziutek/mymysql/thrsafe" //
Thread safe engine
)
func main() {
db := mysql.New("tcp", "", "127.0.0.1:3306", user,
pass, dbname)
err := db.Connect()
if err != nil {
panic(err)
}
rows, res, err := db.Query("select * from X where
id > %d", 20)
if err != nil {
panic(err)
}
https://github.com/ziutek/mymysql
for _, row := range rows {
for _, col := range row {
if col == nil {
// col has NULL value
} else {
// Do something with text in col (type
[]byte)
}
}
// You can get specific value from a row
val1 := row[1].([]byte)
// You can use it directly if conversion isn't
needed
os.Stdout.Write(val1)
// You can get converted value
number := row.Int(0) // Zero value
str := row.Str(1) // First value
bignum := row.MustUint(2) // Second value
// You may get values by column name
first := res.Map("FirstColumn")
second := res.Map("SecondColumn")
val1, val2 := row.Int(first), row.Str(second)
}
}
log
package main
import (
"bytes"
"fmt"
"log"
)
func main() {
var buf bytes.Buffer
logger := log.New(&buf, "logger: ", log.Lshortfile)
logger.Print("Hello, log file!")
fmt.Print(&buf)
}
 logger: main.go:12: Hello, log file!
log - level
• 로그레벨에 따라 로깅하는 패키지는 기본 SDK에 없다.
• https://github.com/jcelliott/lumber
• 콘솔로거
log := lumber.NewConsoleLogger(lumber.WARN)
• 파일로거
log := lumber.NewFileLogger("filename.log", lumber.INFO, lumber.ROTATE, 5000, 9, 100)
• 파일로거 (rotate)
log := lumber.NewRotateLogger("filename.log", 5000, 9)
• 사용법
log.Trace("the %s log level", "lowest")
log.Debug("")
log.Info("the default log level")
log.Warn("")
log.Error("")
log.Fatal("the %s log level", "highest")
• 로그앞에 prefix 붙이기
log.Prefix("MYAPP")
끝
수고하셨어요~♥

Más contenido relacionado

La actualidad más candente (20)

Angular Directives
Angular DirectivesAngular Directives
Angular Directives
 
Javascript
JavascriptJavascript
Javascript
 
Html intro
Html introHtml intro
Html intro
 
HTTP request and response
HTTP request and responseHTTP request and response
HTTP request and response
 
Hibernate ppt
Hibernate pptHibernate ppt
Hibernate ppt
 
Introduction to HTML5
Introduction to HTML5Introduction to HTML5
Introduction to HTML5
 
01 Php Introduction
01 Php Introduction01 Php Introduction
01 Php Introduction
 
Basics PHP
Basics PHPBasics PHP
Basics PHP
 
Lesson 5 php operators
Lesson 5   php operatorsLesson 5   php operators
Lesson 5 php operators
 
Asp.net state management
Asp.net state managementAsp.net state management
Asp.net state management
 
4.2 PHP Function
4.2 PHP Function4.2 PHP Function
4.2 PHP Function
 
Php operators
Php operatorsPhp operators
Php operators
 
HTML Text formatting tags
HTML Text formatting tagsHTML Text formatting tags
HTML Text formatting tags
 
PHP - Introduction to PHP Fundamentals
PHP -  Introduction to PHP FundamentalsPHP -  Introduction to PHP Fundamentals
PHP - Introduction to PHP Fundamentals
 
Php introduction
Php introductionPhp introduction
Php introduction
 
jpa-hibernate-presentation
jpa-hibernate-presentationjpa-hibernate-presentation
jpa-hibernate-presentation
 
Css
CssCss
Css
 
HTML5
HTML5HTML5
HTML5
 
javascript objects
javascript objectsjavascript objects
javascript objects
 
JavaScript - Chapter 9 - TypeConversion and Regular Expressions
 JavaScript - Chapter 9 - TypeConversion and Regular Expressions  JavaScript - Chapter 9 - TypeConversion and Regular Expressions
JavaScript - Chapter 9 - TypeConversion and Regular Expressions
 

Destacado

Redis: Lua scripts - a primer and use cases
Redis: Lua scripts - a primer and use casesRedis: Lua scripts - a primer and use cases
Redis: Lua scripts - a primer and use casesRedis Labs
 
Openstack Rally - Benchmark as a Service. Openstack Meetup India. Ananth/Rahul.
Openstack Rally - Benchmark as a Service. Openstack Meetup India. Ananth/Rahul.Openstack Rally - Benchmark as a Service. Openstack Meetup India. Ananth/Rahul.
Openstack Rally - Benchmark as a Service. Openstack Meetup India. Ananth/Rahul.Rahul Krishna Upadhyaya
 
Hancom MDS Conference - KAKAO DEVOPS Practice (카카오 스토리의 Devops 사례)
Hancom MDS Conference - KAKAO DEVOPS Practice (카카오 스토리의 Devops 사례)Hancom MDS Conference - KAKAO DEVOPS Practice (카카오 스토리의 Devops 사례)
Hancom MDS Conference - KAKAO DEVOPS Practice (카카오 스토리의 Devops 사례)knight1128
 
LinkedIn Data Infrastructure (QCon London 2012)
LinkedIn Data Infrastructure (QCon London 2012)LinkedIn Data Infrastructure (QCon London 2012)
LinkedIn Data Infrastructure (QCon London 2012)Sid Anand
 

Destacado (6)

ScalaBlitz
ScalaBlitzScalaBlitz
ScalaBlitz
 
Scala Parallel Collections
Scala Parallel CollectionsScala Parallel Collections
Scala Parallel Collections
 
Redis: Lua scripts - a primer and use cases
Redis: Lua scripts - a primer and use casesRedis: Lua scripts - a primer and use cases
Redis: Lua scripts - a primer and use cases
 
Openstack Rally - Benchmark as a Service. Openstack Meetup India. Ananth/Rahul.
Openstack Rally - Benchmark as a Service. Openstack Meetup India. Ananth/Rahul.Openstack Rally - Benchmark as a Service. Openstack Meetup India. Ananth/Rahul.
Openstack Rally - Benchmark as a Service. Openstack Meetup India. Ananth/Rahul.
 
Hancom MDS Conference - KAKAO DEVOPS Practice (카카오 스토리의 Devops 사례)
Hancom MDS Conference - KAKAO DEVOPS Practice (카카오 스토리의 Devops 사례)Hancom MDS Conference - KAKAO DEVOPS Practice (카카오 스토리의 Devops 사례)
Hancom MDS Conference - KAKAO DEVOPS Practice (카카오 스토리의 Devops 사례)
 
LinkedIn Data Infrastructure (QCon London 2012)
LinkedIn Data Infrastructure (QCon London 2012)LinkedIn Data Infrastructure (QCon London 2012)
LinkedIn Data Infrastructure (QCon London 2012)
 

Similar a Let's Go (golang)

GopherCon Korea 2015 - Python 개발자를 위한 Go (이경찬)
GopherCon Korea 2015 - Python 개발자를 위한 Go (이경찬)GopherCon Korea 2015 - Python 개발자를 위한 Go (이경찬)
GopherCon Korea 2015 - Python 개발자를 위한 Go (이경찬)Kyoungchan Lee
 
Effective c++ chapter1 2_dcshin
Effective c++ chapter1 2_dcshinEffective c++ chapter1 2_dcshin
Effective c++ chapter1 2_dcshinDong Chan Shin
 
2013 C++ Study For Students #1
2013 C++ Study For Students #12013 C++ Study For Students #1
2013 C++ Study For Students #1Chris Ohk
 
불어오는 변화의 바람, From c++98 to c++11, 14
불어오는 변화의 바람, From c++98 to c++11, 14 불어오는 변화의 바람, From c++98 to c++11, 14
불어오는 변화의 바람, From c++98 to c++11, 14 명신 김
 
파이썬 스터디 2주차
파이썬 스터디 2주차파이썬 스터디 2주차
파이썬 스터디 2주차Han Sung Kim
 
NHNNEXT 개경프14 Subway Rocket Team Study 3rd C++
NHNNEXT 개경프14 Subway Rocket Team Study 3rd C++NHNNEXT 개경프14 Subway Rocket Team Study 3rd C++
NHNNEXT 개경프14 Subway Rocket Team Study 3rd C++Min-soo Park
 
파이썬 데이터과학 레벨1 - 초보자를 위한 데이터분석, 데이터시각화 (2020년 이태영)
파이썬 데이터과학 레벨1 - 초보자를 위한 데이터분석, 데이터시각화 (2020년 이태영) 파이썬 데이터과학 레벨1 - 초보자를 위한 데이터분석, 데이터시각화 (2020년 이태영)
파이썬 데이터과학 레벨1 - 초보자를 위한 데이터분석, 데이터시각화 (2020년 이태영) Tae Young Lee
 
Python programming for Bioinformatics
Python programming for BioinformaticsPython programming for Bioinformatics
Python programming for BioinformaticsHyungyong Kim
 
[C++ Korea 2nd Seminar] C++17 Key Features Summary
[C++ Korea 2nd Seminar] C++17 Key Features Summary[C++ Korea 2nd Seminar] C++17 Key Features Summary
[C++ Korea 2nd Seminar] C++17 Key Features SummaryChris Ohk
 
A tour of C++ : the basics
A tour of C++ : the basicsA tour of C++ : the basics
A tour of C++ : the basicsJaewon Choi
 
[NDC2016] TERA 서버의 Modern C++ 활용기
[NDC2016] TERA 서버의 Modern C++ 활용기[NDC2016] TERA 서버의 Modern C++ 활용기
[NDC2016] TERA 서버의 Modern C++ 활용기Sang Heon Lee
 
Api design for c++ 6장
Api design for c++ 6장Api design for c++ 6장
Api design for c++ 6장Ji Hun Kim
 
C++ Advanced 강의 5주차
C++ Advanced 강의 5주차C++ Advanced 강의 5주차
C++ Advanced 강의 5주차HyunJoon Park
 
스위프트 성능 이해하기
스위프트 성능 이해하기스위프트 성능 이해하기
스위프트 성능 이해하기Yongha Yoo
 
Modern C++ 프로그래머를 위한 CPP11/14 핵심
Modern C++ 프로그래머를 위한 CPP11/14 핵심Modern C++ 프로그래머를 위한 CPP11/14 핵심
Modern C++ 프로그래머를 위한 CPP11/14 핵심흥배 최
 
5장 객체와클래스
5장 객체와클래스5장 객체와클래스
5장 객체와클래스SeoYeong
 
자바스크립트 함수
자바스크립트 함수자바스크립트 함수
자바스크립트 함수유진 변
 

Similar a Let's Go (golang) (20)

GopherCon Korea 2015 - Python 개발자를 위한 Go (이경찬)
GopherCon Korea 2015 - Python 개발자를 위한 Go (이경찬)GopherCon Korea 2015 - Python 개발자를 위한 Go (이경찬)
GopherCon Korea 2015 - Python 개발자를 위한 Go (이경찬)
 
Effective c++ chapter1 2_dcshin
Effective c++ chapter1 2_dcshinEffective c++ chapter1 2_dcshin
Effective c++ chapter1 2_dcshin
 
2013 C++ Study For Students #1
2013 C++ Study For Students #12013 C++ Study For Students #1
2013 C++ Study For Students #1
 
불어오는 변화의 바람, From c++98 to c++11, 14
불어오는 변화의 바람, From c++98 to c++11, 14 불어오는 변화의 바람, From c++98 to c++11, 14
불어오는 변화의 바람, From c++98 to c++11, 14
 
파이썬 스터디 2주차
파이썬 스터디 2주차파이썬 스터디 2주차
파이썬 스터디 2주차
 
NHNNEXT 개경프14 Subway Rocket Team Study 3rd C++
NHNNEXT 개경프14 Subway Rocket Team Study 3rd C++NHNNEXT 개경프14 Subway Rocket Team Study 3rd C++
NHNNEXT 개경프14 Subway Rocket Team Study 3rd C++
 
파이썬 데이터과학 레벨1 - 초보자를 위한 데이터분석, 데이터시각화 (2020년 이태영)
파이썬 데이터과학 레벨1 - 초보자를 위한 데이터분석, 데이터시각화 (2020년 이태영) 파이썬 데이터과학 레벨1 - 초보자를 위한 데이터분석, 데이터시각화 (2020년 이태영)
파이썬 데이터과학 레벨1 - 초보자를 위한 데이터분석, 데이터시각화 (2020년 이태영)
 
Python programming for Bioinformatics
Python programming for BioinformaticsPython programming for Bioinformatics
Python programming for Bioinformatics
 
[C++ Korea 2nd Seminar] C++17 Key Features Summary
[C++ Korea 2nd Seminar] C++17 Key Features Summary[C++ Korea 2nd Seminar] C++17 Key Features Summary
[C++ Korea 2nd Seminar] C++17 Key Features Summary
 
A tour of C++ : the basics
A tour of C++ : the basicsA tour of C++ : the basics
A tour of C++ : the basics
 
[NDC2016] TERA 서버의 Modern C++ 활용기
[NDC2016] TERA 서버의 Modern C++ 활용기[NDC2016] TERA 서버의 Modern C++ 활용기
[NDC2016] TERA 서버의 Modern C++ 활용기
 
Api design for c++ 6장
Api design for c++ 6장Api design for c++ 6장
Api design for c++ 6장
 
HI-ARC PS 101
HI-ARC PS 101HI-ARC PS 101
HI-ARC PS 101
 
06장 함수
06장 함수06장 함수
06장 함수
 
C++ Advanced 강의 5주차
C++ Advanced 강의 5주차C++ Advanced 강의 5주차
C++ Advanced 강의 5주차
 
스위프트 성능 이해하기
스위프트 성능 이해하기스위프트 성능 이해하기
스위프트 성능 이해하기
 
Modern C++ 프로그래머를 위한 CPP11/14 핵심
Modern C++ 프로그래머를 위한 CPP11/14 핵심Modern C++ 프로그래머를 위한 CPP11/14 핵심
Modern C++ 프로그래머를 위한 CPP11/14 핵심
 
Boost
BoostBoost
Boost
 
5장 객체와클래스
5장 객체와클래스5장 객체와클래스
5장 객체와클래스
 
자바스크립트 함수
자바스크립트 함수자바스크립트 함수
자바스크립트 함수
 

Más de 상욱 송

클레이튼 BApp 서비스 현황
클레이튼 BApp 서비스 현황클레이튼 BApp 서비스 현황
클레이튼 BApp 서비스 현황상욱 송
 
쿠버네티스의 이해 #2
쿠버네티스의 이해 #2쿠버네티스의 이해 #2
쿠버네티스의 이해 #2상욱 송
 
쿠버네티스의 이해 #1
쿠버네티스의 이해 #1쿠버네티스의 이해 #1
쿠버네티스의 이해 #1상욱 송
 
이더리움 스마트계약 보안지침 가이드 2. 솔리디티 권고안
이더리움 스마트계약 보안지침 가이드 2. 솔리디티 권고안이더리움 스마트계약 보안지침 가이드 2. 솔리디티 권고안
이더리움 스마트계약 보안지침 가이드 2. 솔리디티 권고안상욱 송
 
Go 언어 성공사례 및 강점
Go 언어 성공사례 및 강점Go 언어 성공사례 및 강점
Go 언어 성공사례 및 강점상욱 송
 
Java 어플리케이션 성능튜닝 Part3
Java 어플리케이션 성능튜닝 Part3Java 어플리케이션 성능튜닝 Part3
Java 어플리케이션 성능튜닝 Part3상욱 송
 
Java 어플리케이션 성능튜닝 Part1
Java 어플리케이션 성능튜닝 Part1Java 어플리케이션 성능튜닝 Part1
Java 어플리케이션 성능튜닝 Part1상욱 송
 
Java 어플리케이션 성능튜닝 Part2
Java 어플리케이션 성능튜닝 Part2Java 어플리케이션 성능튜닝 Part2
Java 어플리케이션 성능튜닝 Part2상욱 송
 
Fastcat 검색구축사례
Fastcat 검색구축사례Fastcat 검색구축사례
Fastcat 검색구축사례상욱 송
 
가상화폐 개념 및 거래 기초개발
가상화폐 개념 및 거래 기초개발가상화폐 개념 및 거래 기초개발
가상화폐 개념 및 거래 기초개발상욱 송
 
클라우드 서비스운영 플랫폼 가루다
클라우드 서비스운영 플랫폼 가루다클라우드 서비스운영 플랫폼 가루다
클라우드 서비스운영 플랫폼 가루다상욱 송
 
범용 PaaS 플랫폼 mesos(mesosphere)
범용 PaaS 플랫폼 mesos(mesosphere)범용 PaaS 플랫폼 mesos(mesosphere)
범용 PaaS 플랫폼 mesos(mesosphere)상욱 송
 
빌링:미터링 Bss platform구현
빌링:미터링 Bss platform구현빌링:미터링 Bss platform구현
빌링:미터링 Bss platform구현상욱 송
 
SaaS Flatform metering and billing
SaaS Flatform metering and billingSaaS Flatform metering and billing
SaaS Flatform metering and billing상욱 송
 
Realtimestream and realtime fastcatsearch
Realtimestream and realtime fastcatsearchRealtimestream and realtime fastcatsearch
Realtimestream and realtime fastcatsearch상욱 송
 
Realtime search engine concept
Realtime search engine conceptRealtime search engine concept
Realtime search engine concept상욱 송
 
네이버 지식쇼핑과 아마존의 검색결과 페이지네비게이션 유형분석
네이버 지식쇼핑과 아마존의 검색결과 페이지네비게이션 유형분석네이버 지식쇼핑과 아마존의 검색결과 페이지네비게이션 유형분석
네이버 지식쇼핑과 아마존의 검색결과 페이지네비게이션 유형분석상욱 송
 

Más de 상욱 송 (17)

클레이튼 BApp 서비스 현황
클레이튼 BApp 서비스 현황클레이튼 BApp 서비스 현황
클레이튼 BApp 서비스 현황
 
쿠버네티스의 이해 #2
쿠버네티스의 이해 #2쿠버네티스의 이해 #2
쿠버네티스의 이해 #2
 
쿠버네티스의 이해 #1
쿠버네티스의 이해 #1쿠버네티스의 이해 #1
쿠버네티스의 이해 #1
 
이더리움 스마트계약 보안지침 가이드 2. 솔리디티 권고안
이더리움 스마트계약 보안지침 가이드 2. 솔리디티 권고안이더리움 스마트계약 보안지침 가이드 2. 솔리디티 권고안
이더리움 스마트계약 보안지침 가이드 2. 솔리디티 권고안
 
Go 언어 성공사례 및 강점
Go 언어 성공사례 및 강점Go 언어 성공사례 및 강점
Go 언어 성공사례 및 강점
 
Java 어플리케이션 성능튜닝 Part3
Java 어플리케이션 성능튜닝 Part3Java 어플리케이션 성능튜닝 Part3
Java 어플리케이션 성능튜닝 Part3
 
Java 어플리케이션 성능튜닝 Part1
Java 어플리케이션 성능튜닝 Part1Java 어플리케이션 성능튜닝 Part1
Java 어플리케이션 성능튜닝 Part1
 
Java 어플리케이션 성능튜닝 Part2
Java 어플리케이션 성능튜닝 Part2Java 어플리케이션 성능튜닝 Part2
Java 어플리케이션 성능튜닝 Part2
 
Fastcat 검색구축사례
Fastcat 검색구축사례Fastcat 검색구축사례
Fastcat 검색구축사례
 
가상화폐 개념 및 거래 기초개발
가상화폐 개념 및 거래 기초개발가상화폐 개념 및 거래 기초개발
가상화폐 개념 및 거래 기초개발
 
클라우드 서비스운영 플랫폼 가루다
클라우드 서비스운영 플랫폼 가루다클라우드 서비스운영 플랫폼 가루다
클라우드 서비스운영 플랫폼 가루다
 
범용 PaaS 플랫폼 mesos(mesosphere)
범용 PaaS 플랫폼 mesos(mesosphere)범용 PaaS 플랫폼 mesos(mesosphere)
범용 PaaS 플랫폼 mesos(mesosphere)
 
빌링:미터링 Bss platform구현
빌링:미터링 Bss platform구현빌링:미터링 Bss platform구현
빌링:미터링 Bss platform구현
 
SaaS Flatform metering and billing
SaaS Flatform metering and billingSaaS Flatform metering and billing
SaaS Flatform metering and billing
 
Realtimestream and realtime fastcatsearch
Realtimestream and realtime fastcatsearchRealtimestream and realtime fastcatsearch
Realtimestream and realtime fastcatsearch
 
Realtime search engine concept
Realtime search engine conceptRealtime search engine concept
Realtime search engine concept
 
네이버 지식쇼핑과 아마존의 검색결과 페이지네비게이션 유형분석
네이버 지식쇼핑과 아마존의 검색결과 페이지네비게이션 유형분석네이버 지식쇼핑과 아마존의 검색결과 페이지네비게이션 유형분석
네이버 지식쇼핑과 아마존의 검색결과 페이지네비게이션 유형분석
 

Let's Go (golang)

  • 1. Let’s Go 2015-3-14 송상욱 swsong at fastcatsearch.com ♥ ♥
  • 2. Why Go? • 클라우드 시스템 관련 Core들이 Go로 작성되고 있음. • 특히 Docker는 Go의 성공사례 • 기존 PaaS를 분석하려고 하니 Go를 읽을 줄 알아야한다. • Github의 Go 프로젝트 59,145개 (2015.3.14기준)
  • 3. Top Github Projects in Go • docker/docker Docker - the open-source application container engine • limetext/lime Open source API-compatible alternative to the text editor Sublime Text • syncthing/syncthing Open Source Continuous File Synchronization • golang/go The Go programming language • GoogleCloudPlatform/kubernetes Container Cluster Manager from Google • go-martini/martini Classy web framework for Go • joewalnes/websocketd Turn any program that uses STDIN/STDOUT into a WebSocket server. Like inetd, but for WebSockets. • github/hub hub helps you win at git. • coreos/etcd A highly-available key value store for shared configuration and service discovery • astaxie/build-web-application-with-golang A golang ebook intro how to build a web with golang 2015.3.14 기준으로 뽑아봤어요
  • 4. 참고문서 • golang-korea – go 개발언어 관련 자료를 한국어로 번역하는 프로젝트 – https://code.google.com/p/golang-korea/ • 그외의 인터넷 문서들
  • 5. 기초 형아들~♥ 이제 부터 나의 기초를 보여줄게 난 생긴것 처럼 단순한 아이야~ ♥ 자 그럼 Let’s Go~♥
  • 6. Go 는 Object-Oriented 언어인가? • 맞기도 하고 아니기도 하다. – http://golang.org/doc/faq#Is_Go_an_object-oriented_language • 아닌 이유 – 상속관계가 없다. No subclass • 맞는 이유 – object-oriented 스타일의 프로그래밍을 허용한다. interface제공. • object-oriented 스타일의 프로그래밍? – 상속은 제공하지 않으며 interface만 제공. – implements"라는 선언 필요없음. – 단순히 해당 인터페이스의 메소드를 구현하기만 하면 인터페이스 사용가능
  • 7. 준비사항 • 홈페이지 : http://golang.org/ • Go SDK 다운로드 : http://golang.org/dl/ • 편집도구 : LiteIDE – 다운로드 : http://sourceforge.net/projects/liteide/files/
  • 8. 함수형태 • 리턴값 없음 func f1() { } • 리턴값 존재 func f1() string { return “OK” } • 리턴값 이름 func f2() (r string) { r = “OK” return } • struct 내부함수 type Counter struct { n int } func (ctr *Counter) add(int amount) { //리시버 Counter 선언. ctr.n += amount; } func f1() (string, int) { return “OK”, 1 } 리시버는 나중에 자세하게 나오니까 염려하지마요
  • 9. Go 가시성 • 최상위 type, 함수, method, 상수, 변수 혹은 구조체의 필드나 method의 이름이 대문자로 시작하면 패키지의 사용자는 접근이 가능 • 반면에 소문자일 경우에는 패키지 내부에서만 접근이 가능
  • 10. 진입점 • main 패키지의 main() 함수 package main func main() { //무언가를 수행한다. }
  • 11. 실행과 빌드 • 실행 $ go run 파일명 • 빌드 $ go build 또는 $ go build 파일명 • 빌드결과삭제 $ go clean
  • 12. 숫자타입 • 정수형 – uint8, uint16, uint32, uint64 – int8, int16, int32, int64 – uint, int, uintptr : 장비의존적 – uint8 == byte – uint32 == rune • 부동소숫점 – float32, float64 • 복소수 – complex64, complex128
  • 13. 그외 모든 타입 bool  불린 true, false numeric  이전 장에서 설명한 숫자타입 string  문자열. Java와 달리 소문자이다. array  [] slice  [] array를 참조한다. ex) arr[2:5] struct  ex) type struct Human { } pointer  * function  func interface  interface map  map channel  chan
  • 14. 키워드 break default func interface select case defer go map struct chan else goto package switch const fallthrough if range type continue for import return var
  • 15. Java와 다른점 몇가지 • 세미콜론은 생략한다. 하지만 같은줄에 여러명령에는 사용. a= 1 b= 2 c=1; d=2 • 변수선언에는 var를 사용하고 타입은 맨뒤에 선언 var a int cf) int a var b string cf) String b • main함수는 파라미터가 없다. 대신 flag사용 var port = flag.String("port", "8080", "Listening port") func main() { flag.Parse() } • if, for 에 괄호를 사용하지 않으며, 여는 중괄호({)는 반드시 같은줄에 사용한다. if x > 1 { .. } for i:=0; i< 100; i++ { //구현 } • 선언과 할당을 동시에 할때는 =가 아닌 := 를 사용한다. 이때 변수타입은 값의 타입으로 추정한다. price := 2000  var price int = 2000 과 동일.
  • 16. Java와 다른점 몇가지 2 • switch-case 는 break가 필요없다. 기본이 break이며, 필요시 fallthrough 사용. • try-catch-finally, throw가 없다. defer  finally raise  throw recover  catch • 포인터존재 var a *Human a := new(Human) b := &i • 사용하지 않는 변수나 import는 컴파일시 에러발생. 제거하거나 주석처리해야한다. • import 에 alias 를 줄 수 있다. import “math” import math2 “my/custom/math” math2.Average(1,2) • private , public 이 없다. 대신 함수명이나 변수명이 대문자이면, public이고 소문자이면 private이다. var Name string  public var price int  private func CallMePublic()  public func callMeInside()  private
  • 17. Java와 다른점 몇가지 3 • class라는 keyword가 없다. 대신 struct를 만들고 함수에 struct명을 주어(리시버) class와 동일하게 사용할 수 있다. • Thread가 없다. 대신 light-weight인 고루틴을 사용한다. go something()  비동기적 something()함수실행 • 여러값을 동시에 리턴가능하다. return a,b,c • 여러값을 동시에 할당가능하다. var a,b,c int = 1,2,3 • 여러변수를 동시에 선언가능하다. import도 동일. • 자동형변환이 안된다. 명시적 형변환필요. var c int = 2000 var d float64 = float64(c)  OK. 만약 var d float64 = c 은 에러. var d float64= float32(c))도 에러. • 배열선업시 괄호는 앞에 쓴다.  []int var ( a int b string ) import ( “fmt” “io” )
  • 18. 변수선언/할당 • 사용법1 var x string = "Hello World" • 사용법2 var x string x = "Hello World" • 사용법3 x := "Hello World" > 일반적으로 많이 사용하는 방식. 타입추정.
  • 19. 변수선언/할당2 • 같은줄에 컴마구분으로 여러변수를 동일 타입으로 정의가능 a int, b int , c int , d int  a, b, c, d int a int, b int, c float64, d float64  a, b int, c, d float64 func f(a, b int, c, d float64) { // do something.. } func main() { f(1, 2, 3., 4.) }
  • 20. 다중값 할당 func f() (int, int) { return 5, 6 } func main() { x, y := f() } • 오류와 함께 반환하는 기능은 자주 사용됨. f, err := os.Open(name, os.O_RDONLY, 0) if err != nil { return err } //파일 f 사용.
  • 21. 다중값 할당2 • 두값의 SWAP이 편하다 • OLD한 방식 a = 10 b = 30 tmp := b b = a a = tmp • Go 방식 a = 10 b= 30 a, b = b, a • 여러개도 된다. a, b, c = b, c, a
  • 22. 다중값 할당3 • 동일한 내용 다른 표현 var ( a int = 1 b int = 2 c int = 3 ) var a int, b int, c int = 1, 2, 3  syntax error: unexpected comma, expecting semicolon or newline or } var a, b, c int = 1, 2, 3 a, b, c := 1, 2, 3
  • 23. 사용하지 않는 변수 • Go 컴파일러는 사용하지 않는 변수존재시 에러발생. func main() { i := 0 } $ go run test.go # command-line-arguments .test.go:16: i declared and not used
  • 24. 문자열 비교 • 자바와 다른점 var x string = "hello" var y string = "hello" fmt.Println(x == y) > true
  • 25. 상수 • 변수 var x string = "Hello World” • 상수 const x string = "Hello World"
  • 26. 상수 • 상수의 Type을 정하지 않으면, 사용될때context에 의해 정해짐. const huge = 1 << 100 fmt.Println(huge)  constant 1267650600228229401496703205376 overflows int fmt.Println(huge >> 40)  4611686018427387904 • iota(Java의 Enum효과) const ( red = iota // red == 0 blue // blue == 1 green // green == 2 )
  • 27. 다중 정의 • 변수 var ( a = 5 b = 10 ) • 상수 const ( Space = " ” Newline = "n" )
  • 28. 다중 정의 • Import import ( "os" "fmt" ) • Type type( book struct { title string price int } coffee struct { size int origin string } )
  • 29. 루프 • For가 유일한 루프. • 괄호가 없다. – 사용법1 for { } – 사용법2 for i < 10 { } – 사용법3 for i:=0 ; i < 10; i++ { }
  • 30. 특별 루프 • Range func main() { x := [5]int{1,2,3,4} for i, value := range x { fmt.Println(value) } } – i : 현재위치(0부터시작) – value : 현재값. x[i] • 컴파일시 에러 : i declared and not used func main() { x := [5]int{1,2,3,4} for _, value := range x { fmt.Println(value) } } – _(언더스코어)는 컴파일러에게 이것이 필요하지 않다고 알려주는 데 사용
  • 31. Switch-Case • 괄호가 없다. • 상수이거나 Integer이 필요가 없다. 문자열도 가능. • Break가 필요없다. 기본적으로 break이며, 통과를 원하면 fallthrough. • switch 값이 생략된 경우에는 기본값은 true가 된다. func main() { str := "3" switch str { case "1": fmt.Println("@1") case "2": fmt.Println("@2") default : fmt.Println("default") } } ---- switch { case i < 0 || i > 0: fmt.Println(”Non-Zero") fallthrough case i == 0 : fmt.Println(”Zero") }
  • 32. Switch-Case • 컴마로 여러 조건가능. switch c { case ' ', '?', '&', '=', '#', '+', '%': … }
  • 33. 배열 • 사용법1 var x [5]int x[0] = 1; x[1] = 2; ;x[2] = 3; x[3] = 4; x[4] = 5 • 사용법2 x := [5]int{1,2,3,4,5} • 사용법3 x := [5]int{ 1,2,3,4, 5, } – 한줄씩 사용할 경우 컴마가 반드시 값뒤에 붙어야하고, 마지막 원소도 반드시 컴마존재. • 사용법4 x := []int{1,2,3,4,5,7,8,9,10} // [1,2,3,4,5,7,8,9,10] 또는 x := []int{} // [] – 배열의 길이를 정하지 않아도 됨.
  • 34. 슬라이스 • 배열을 참조하는 일부를 가리킴.데이터공유 arr := []int{1,2,3,4,5} x := arr[0:3] // 0<=i<3  [1,2,3] x := arr[:3] // i<3  [0:3]과 동일 x := arr[3:] // i >= 3  [4,5] • 선언 var x []float64 • 생성 x := make([]float64, 5) x := make([]float64, 5, 10)
  • 35. 슬라이스 • 배열을 참조하는 일부를 가리킴.데이터공유 arr := []int{1,2,3,4,5} x := arr[0:3] // 0<=i<3  [1,2,3] x := arr[:3] // i<3  [0:3]과 동일 x := arr[3:] // i >= 3  [4,5] • 선언 var x []float64 • 생성 x := make([]float64, 5) x := make([]float64, 5, 10)
  • 36. 슬라이스 관련함수 • append slice1 := []int{1,2,3} slice2 := append(slice1, 4, 5) // 4,5 를 추가. // slice1  [1,2,3] // slice2  [1,2,3,4,5] • copy slice1 := []int{1,2,3} slice2 := make([]int, 2) // 길이가 2인 슬라이스 copy(slice2, slice1) // slice1  [1,2,3] // slice2  [1,2]
  • 37. 맵 • Key는 동등연산자(==)이 가능한 integer, float, 복소수, string, 포인터, 그리고 인터페이스와 같이 어떤 타입이든 가능 • struct와 배열,slice는 동등연산을 할 수 없기 때문에 불가. • 사용법1 var x map[string]int x = make(map[string]int) x["a"]=1; x["b"]=2; x["c"]=3 • 사용법2 x := make(map[string]int) x["a"]=1; x["b"]=2; x["c"]=3 • 사용법3 x := map[string]int{"a":1, "b":2, "c":3}
  • 38. 맵 • 참조 name := x[”aaaa"] 또는 name, ok := x[”aaaa"] fmt.Println(name, ok) • 삭제 delete(x, "b") • 갯수확인 len(x)
  • 39. 다중맵 elements := map[string]map[string]string{ "H": map[string]string{ "name":"Hydrogen", "state":"gas", }, "He": map[string]string{ "name":"Helium", "state":"gas", }, }
  • 40. 가변함수 func add(args ...int) int { total := 0 for _, v := range args { total += v } return total } • add(1,2,3)  OK • xs := []int{1,2,3} add(xs)  Error. 가변인자는 슬라이스와 호환되지 않는다. • add(xs...)  OK. 가변인자 변수자체를 전달할때는 ...을 붙여야 인식됨. 가변인자는 add(foo...)와 같이 ...를 반드시 붙어야해요
  • 41. 클로저 func main() { add := func(x, y int) int { return x + y } fmt.Println(add(1,1)) } --------------------------------------------------------------------------------------------- func makeEvenGenerator() func() uint { i := uint(0) return func() (ret uint) { ret = i i += 2 return } } func main() { nextEven := makeEvenGenerator() fmt.Println(nextEven()) // 0 fmt.Println(nextEven()) // 2 fmt.Println(nextEven()) // 4 }
  • 42. Defer (지연된 호출) • 해당함수 종료시 실행됨. • Java의 try-finally 대체 func main() { defer second() first() } ------------------------------------------------ f, _ := os.Open(filename) defer f.Close() • 장점 1. Close 호출을 Open 호출 가까이에 둬서 이해하기가 쉽다. 2. 함수에 return이 여러 개 있더라도 Close가 어떠한 return 시라도 호출 3. 지연된 함수는 런타임 패닉이 일어나더라도 실행
  • 43. Panic & Recover • Java의 throw-catch 를 대체 • panic : 런타임오류 강제발생 • recover : 런타임패닉 처리 • 잘못된 사용예. recover가 호출기도 전에 종료. panic("PANIC") str := recover() • 올바른 사용예. defer와 짝을 맞춤. 익명함수 사용. defer func() { str := recover() fmt.Println(str) }() panic("PANIC”) • 사용목적 – 범위를 벗어난 배열 인덱스에 접근시 에러처리 – 맵을 초기화하는 것을 잊어버릴 경우 에러처리
  • 45. 포인터 • Address 연산자로 포인터 사용 func one(xPtr *int) { *xPtr = 0 } func main() { x := 5 one(&x) fmt.Println(x) // x는 1 } ---------------------------- • new 로 포인터 사용 func main() { xPtr := new(int) one(xPtr) fmt.Println(*xPtr) // x는 1 }
  • 46. 포인터 접근 type Rectangle struct { length, width int } func main() { var r *Rectangle r = new(Rectangle) // Rectangle에 대한 포인터 반환. r.length = 5 (*r).length = 5 //r.length=5와 동일하다. fmt.Println(r.length) //  5 fmt.Println((*r).length) //  5 } • c++과 달리 -> 가 없다. 포인터, 인스턴스 모두에 대해 dot(.) 노테이션 사용
  • 47. Struct • Go는 클래스가 없다. • 하지만 클래스와 동일한걸 만들수 있다. • Java에서 Rectangle 클래스는 area()메소드를 가지고 있음 //JAVA public class Rectangle { private float x1, y2, x2, y2; public float area() { float l = distance(x1, y1, x1, y2); float w = distance(x1, y1, x2, y1); return l * w; } private float distance(float x1, float y1, float x2, float y2) { float a = x2 - x1; float b = y2 - xy; return Math.sqrt(a*a + b*b); } }
  • 48. Struct //C++ class rectangle { private: float x1, y2, x2, y2; public: float area(void); } inline float rectangle::area() { float l = distance(x1, y1, x1, y2); float w = distance(x1, y1, x2, y1); return l * w; } float distance(float x1, float y1, float x2, float y2) { float a = x2 - x1; float b = y2 - xy; return sqrt(a*a + b*b); }
  • 49. Struct • Receiver를 사용하여 특정 type에 종속적 함수를 생성한다. //Go type Rectangle struct { x1, y1, x2, y2 float64 } func (r *Rectangle) area() float64 { l := distance(r.x1, r.y1, r.x1, r.y2) w := distance(r.x1, r.y1, r.x2, r.y1) return l * w } func distance(x1, y1, x2, y2 float64) float64 { a := x2 – x1 b := y2 – y1 return math.Sqrt(a*a + b*b) } func main() { r := Rectangle{1, 5, 3, 7} fmt.Println(r) //  {1 5 3 7} }
  • 50. Struct • 리시버는 포인터 or 객체중 어느걸 써야할까? type Rectangle struct { length, width int } func (r Rectangle) set(i, j int) { r.length = i r.width = j } ----- • Receiver는 아래 두가지 모두 사용가능. func (r Rectangle) set(i, j int) { .. } // OK func (r *Rectangle) set(i, j int) { .. } // OK
  • 51. Struct 1. 객체 사용시 func (r Rectangle) set(i, j int) { r.length = i r.width = j } func main() { r := Rectangle{1, 5} r.set(10, 50) fmt.Println(r) //  [1 5] 안바뀐다. r이 set함수에 복사되어 전달됨. shallow copy. } 2. 포인터 사용시 func (r *Rectangle) set(i, j int) { ..} 결과 [10 50] 변경됨. call by reference.
  • 52. Struct • 생성방식 type Rectangle struct { length, width int } var r Rectangle // Rectangle타입. 내용은 length=0, width=0 var r *Rectangle // *Rectangle타입. 내용은 nil. r := new(Rectangle) // *Rectangle타입. 내용은 length=0, width=0 r := Rectangle{width:10, length: 50} // Rectangle타입. 이름명시 r := Rectangle{10, 50} // Rectangle타입. 순서대로 할당
  • 53. Struct – embedded type type Person struct { Name string } • HAS-A 관계 type Android struct { Person person Model string } a.person.Name=5 //Person을 통해서 접근 • IS-A 관계 type Android struct { Person //Android is a person Model string } a := new(Android) a.Name=5 // Android가 Person인것 처럼 접근가능.
  • 54. Struct –기본 타입 확장 • 기존 int 타입을 기반으로 string() 함수를 붙인다. #src/fmt/stringer_test.go 참조 type TI int func (v TI) String() string { return fmt.Sprintf("I: %d", int(v)) } • Java라면 public class IntegerType extends Integer { public String string() { .. } } $ javac IntegerType.java IntegerType.java:1: error: cannot inherit from final Integer public class IntegerType extends Integer { ^ 1 error  Integer는 Final class 이므로 확장 불가.
  • 55. Interface • Rectangle type Rectangle struct { x1, y1, x2, y2 float64 } func (r *Rectangle) area() float64 { .. } • Circle type Circle struct { x, y, r float64 } func (c *Circle) area() float64 { .. } • Shape type Shape interface { area() float64 } • 사용시 func totalArea(shapes ...Shape) float64 { .. } 어떠한 선언적 종속관계도 없다!!
  • 57. 고루틴(go) package main import ( "fmt" "math/rand" "time" ) func f(n int) { amt := time.Duration(rand.Intn(250)) time.Sleep(time.Millisecond * amt) fmt.Println(n) } func main() { for i := 0; i < 1000000; i++ { go f(i) } var input string fmt.Scanln(&input) }
  • 58. 채널(chan) • 채널(channel)은 두 고루틴이 서로 통신하고 실행흐름을 동기화하는 수단을 제공 func main() { c := make(chan string) c <- "oce” msg := <-c fmt.Println(msg) } 결과 $ go run main.go fatal error: all goroutines are asleep - deadlock! • main함수는 첫번째 고루틴이다.
  • 59. 채널(chan) func main() { c := make(chan string) go func() { // 익명 함수의 고루틴 c <- "oce” }() msg := <-c fmt.Println(msg) } 결과 $ go run main.go oce • 비동기 채널설정 기본적으로 채널은 동기적. 버퍼를 주면 비동기적으로 동작가능. c := make(chan int, 1) //길이가 1인 버퍼설정.
  • 60. 채널(chan) - 방향 • 양방향 func f(c chan string) • 입력전용 func f(c chan<- string) • 출력전용 func f(c <-chan string)
  • 61. Select c1 := make(chan string) c2 := make(chan string) select { case msg1 := <- c1: fmt.Println("Message 1", msg1) case msg2 := <- c2: fmt.Println("Message 2", msg2) case <- time.After(time.Second): fmt.Println("timeout") default: fmt.Println("nothing ready") }
  • 63. 초기화 • func init() 이 존재하면 main()보다도 먼저실행 • init()은 해당패키지 import시 실행 – import “abc” 가 실행시 abc.go내 init()이 실행된다. • init() 여러번 중복해서 선언될수 있으며, 코드 순서대로 순차적 실행 package main import "fmt” var i = foo() func foo() int { fmt.Println("Call foo()") return 1 } func init() { fmt.Println("Call init() 1") } func init() { fmt.Println("Call init() 2") } func main() { fmt.Println("Call main()") } func init() { fmt.Println("Call init() 3") } 실행결과 Call foo() Call init() 1 Call init() 2 Call init() 3 Call main()
  • 64. make()와 new()의 차이 • make() – 오로지 slice, map, channel을 만드는 용도로만 사용. – 포인터를 반환하지 않음. 즉 *T가 아닌 T타입을 리턴. var p *[]int = new([]int) // slice구조를 할당함; *p == nil; 그다지 유용하지 않음 var v []int = make([]int, 100) // slice v는 이제 100개의 int를 가지는 새로운 배열을 참조함 // new : 불필요하게 복잡함: var p *[]int = new([]int) *p = make([]int, 100, 100) // make: 자연스러움: v := make([]int, 100)
  • 65. Conversion var f1 float64 = 6.0 f2 := 12 / f1 // 상수 12는 float64로 자동변환  2 var i int = 12 var f1 float64 = 6.0 f2 := i / f1 // 변수타입은 자동변환되지 않는다.  invalid operation: i / f1 (mismatched types int and float64) var i = 12. //12. 은 float64 형이다. var f1 float32 = 6.0 f2 := i / f1 //심지어 같은 float형이라도 float32와 float64는 자동형변환 불가.  invalid operation: i / f1 (mismatched types float64 and float32)
  • 66. Conversion var i = 12. var f1 float32 = 6.0 f2 := i / f1  ERROR var i = 12. var f1 float32 = 6.0 f2 := float32(i) / f1  2 i := 12 fmt.Println(”Result = ” + i)  cannot convert "Result=" to type int invalid operation: "Result=" + i (mismatched types string and int) import ”strconv” i := 12 fmt.Println("Result = " + strconv.Itoa(i))  Result = 3
  • 67. GOROOT • GOROOT는 Go SDK의 설치위치를 나타내며, 이 위치하위에서 기본 라이브러리와 문서등을 찾아서 사용한다. • Go 기본설치위치 – *nix : /usr/local/go – Windows : C:Go • 만약 다른 곳에 설치했다면 GOROOT 환경변수를 설정해주어야함. – ex) /application/go에 설치했다면, export GOROOT=/application/go export PATH=$PATH:$GOROOT/bin – *nix계열은 .bash_profile과 같은 설정파일에 추가한다. • 기본위치에 설치되어 있다면 GOROOT를 설정할 필요없음
  • 68. GOPATH • Java에는 classpath, Go에는 GOPATH • import 시 GOPATH의 경로를 찾음 • *Nix계열은 콜론, Windows는 세미콜론으로 연결된 경로 리스트 GOPATH=/home/user/gocode /home/user/gocode/ src/ foo/ bar/ (go code in package bar) x.go grep2/ (go code in package main) y.go bin/ grep2 (installed command) pkg/ linux_amd64/ oce/ bar.a (installed package object) Tip: GOPATH가 여러개일때 특정 src하위에서 install 된 패키지파일은 해당 고패스하위로 들어간다.
  • 69. 패키지 GOPATH=<User Home Directory>/go $ cd go $ mkdir -p src/math2 $ cd src/math2 $ vi foo.go # 파일명과 패키지 명이 동일할 필요없음. package math2 // 패키지명은 폴더와 이름이 일치해야함. func Average(i, j int) float64 { // average가 아닌 대문자 Average로 선언. import후 호출가능함 return float64(i + j) / 2 } $ go install  <User Home Directory>/go/pkg/darwin_amd64/math2.a 생성됨. ------------------- package main import “fmt” import “math2” func main() { i := math2.Average(10,30) // 20 fmt.Println(“i=“, i) } > 패키지명을 math로 하면 이미 존재하는 go의 기본패키지명과 겹치므로 go install시 에러발생.
  • 70. 패키지 • 최상위가 아닌 중간경로를 주면 math라는 이름으로 패키지 생성가능. $ mkdir -p src/oce.org/math $ cd src/oce.org/math $ vi foo.go package math func Average(i, j int) float64 { return float64(i + j) / 2 } $ go install  <User Home Directory>/go/pkg/darwin_amd64/oce.org/math.a 생성됨. ------------------- package main import “fmt” import “oce.org/math” func main() { i := math.Average(10,30) // 20 fmt.Println(“i=“, i) }
  • 71. 패키지 • 패키지 이름의 중복을 방지하기 위하여 import시 Alias가능 package main import “fmt” import “math” import math2 “oce.org/math” func main() { i := math.Average(10,30) j := math2.Average(10,30) fmt.Println(“i=“, i, “j=“, j) }
  • 72. 패키지 • Alias를 Dot(.) 으로 하면 해당패키지를 이름없이 바로 접근가능. package main import . “fmt” func main() { Println(“Called without package name!”) }
  • 74. 문서화 • Java에는 javadoc, Go에는 godoc • usage: godoc package [name ...] godoc -http=:6060 $ godoc oce.org/math PACKAGE DOCUMENTATION package math import "oce.org/math” FUNCTIONS func Average(i, j int) float64 $ godoc oce.org/math average  대소문자구분 No match found. $ godoc oce.org/math Average func Average(i, j int) float64 $godoc –http=:6060  로컬 웹서버시작  http://localhost:6060/pkg/
  • 75. 문서화 //Copyright 2015 // oce.org에서 제공하는 수학패키지. //  빈줄삽입. // 2015-3-14 업데이트. package math // 평균을 구한다. // 입력값은 i,j 정수를 받아들인다. // 리턴값은 float64이다. // // 입력값: // i 첫번째정수  Tab을 넣었다. // j 두번째정수  Tab을 넣었다. func Average(i, j int) float64 { return float64(i + j) / 2 } 주석에 Tab이 들어있으면, 회색Box안으로 표시되요
  • 76. 문서화 $ go install; godoc oce.org/math PACKAGE DOCUMENTATION package math import "oce.org/math" oce.org에서 제공하는 수학패키지.  빈줄이 나타났다. 2015-3-14 업데이트. FUNCTIONS func Average(i, j int) float64 평균을 구한다. 입력값은 i,j 정수를 받아들인다. 리턴값은 float64이다.  주석내 개행은 무시된다. 입력값: i 첫번째정수 j 두번째정수
  • 78. 문서화 http://localhost:6060/pkg/oce.org/math/$ godoc -http=:6060 가장 좋은 문서화예제는 Go sdk의 소스에 있어요. <GOROOT>/src/fmt/print.go <GOROOT>/src/fmt/doc.go 를 참조하세요.
  • 79. 문서화 • Example 도 넣을수 있다. 패키지 os/exec/
  • 80. 문서화 • 함수정의 (src/os/exec/exec.go, src/os/exec/lp_unix.go) func LookPath(file string) (string, error) { .. } func (c *Cmd) Start() error { .. } • 예제정의(src/os/exec/example_test.go) func ExampleLookPath() { path, err := exec.LookPath("fortune") if err != nil { log.Fatal("installing fortune is in your future")  이 소스가 예제항목으로 삽입된다. } fmt.Printf("fortune is available at %sn", path) } func ExampleCmd_Start() { cmd := exec.Command("sleep", "5") err := cmd.Start() if err != nil { log.Fatal(err)  이 소스가 예제항목으로 삽입된다. } log.Printf("Waiting for command to finish...") err = cmd.Wait() log.Printf("Command finished with error: %v", err) }
  • 81. 테스트 • 테스트 함수만드는 법 – 파일이름은 _test.go로 끝난다. – 함수이름이 Test로 시작 – *testing.T를 인자로 받을것 (import “testing”) • 예제 # foo_test.go package math import "testing" func TestAverage(t *testing.T) { var v float64 v = Average([]float64{1,2}) if v != 1.5 { t.Error("Expected 1.5, got ", v) } }
  • 82. 테스트 $ go test PASS ok oce.org/math 0.003s • 만약 파일명이 _test.go, test.go, foo_testing.go 등 파일명규칙을 따르지 않을때는 아래와 같이 테스트파일을 못찾는다. $ go test ? oce.org/math [no test files] • fmt 패키지내 파일 리스트 참고 (경로 <GOROOT>/src/fmt) doc.go export_test.go fmt_test.go format.go print.go scan.go scan_test.go stringer_test.go
  • 83. 테스트 import "testing" type testpair struct { values []float64 average float64 } var tests = []testpair{ { []float64{1,2}, 1.5 }, { []float64{1,1,1,1,1,1}, 1 }, { []float64{-1,1}, 0 }, } func TestAverage(t *testing.T) { for _, pair := range tests { v := Average(pair.values) if v != pair.average { t.Error( "For", pair.values, "expected", pair.average, "got", v, ) } } } struct를 이용하면 여러 테스트값을 편하게 테스트해볼 수 있어요.
  • 85. strings strings.Contains("test", "es") // true strings.Count("test", "t") // 2 strings.HasPrefix("test", "te") // true strings.HasSuffix("test", "st") // true strings.Index("test", "e") // 1 strings.Join([]string{"a","b"}, "-") // "a-b" strings.Repeat("a", 5) // "aaaaa" strings.Replace("aaaa", "a", "b", 2) // "bbaa" strings.Split("a-b-c-d-e", "-") // []string{"a","b","c","d","e"} strings.ToLower("TEST") // "test" strings.ToUpper("test") // "TEST” ---- arr := []byte("test") str := string([]byte{'t','e','s','t'}) 더 많은 정보는 여기있어요 https://golang.org/pkg/strings
  • 86. io • 함수정의 보다는 대부분이 interface로 구성 • 주요 인터페이스는 Reader와 Writer • Reader는 Read(), Writer는 Write() 지원 • Reader  Writer 데이터 복사 – func Copy(dst Writer, src Reader) (written int64, err error) 더 많은 정보는 여기있어요 https://golang.org/pkg/io
  • 87. bytes package main import ( "bytes" "fmt" "os" ) func main() { var b bytes.Buffer // 버퍼는 초기화가 필요없다. 선언후 그대로 사용. b.Write([]byte("Hello ")) fmt.Fprintf(&b, "world!") b.WriteTo(os.Stdout) } ----- func main() { // string 이나 []byte 를 io.Reader 로 바꿔준다. buf := bytes.NewBufferString("R29waGVycyBydWxlIQ==") dec := base64.NewDecoder(base64.StdEncoding, buf) io.Copy(os.Stdout, dec) } 더 많은 정보는 여기있어요 https://golang.org/pkg/bytes
  • 88. os • 파일열기 : os.Open() • 파일닫기 : file.Close() package main import ( "fmt" "os" ) func main() { file, err := os.Open("test.txt") if err != nil { // 오류를 처리 return } defer file.Close() // 파일의 크기를 구함 stat, err := file.Stat() if err != nil { return } // 파일을 읽음 bs := make([]byte, stat.Size()) _, err = file.Read(bs) if err != nil { return } str := string(bs) fmt.Println(str) }
  • 89. error • 오류에 대한 내장타입 • error.New() 사용시 자체오류 생성가능 package main import ( "errors" "fmt" ) func main() { err := errors.New("emit macho dwarf: elf header corrupted") if err != nil { fmt.Print(err) } } ----- func main() { const name, id = "bimmler", 17 err := fmt.Errorf("user %q (id %d) not found", name, id) if err != nil { fmt.Print(err) } }
  • 90. container heap Package heap provides heap operations for any type that implements heap.Interface. list Package list implements a doubly linked list. ring Package ring implements operations on circular lists. package main import ( "container/list" "fmt" ) func main() { // Create a new list and put some numbers in it. l := list.New() e4 := l.PushBack(4) e1 := l.PushFront(1) l.InsertBefore(3, e4) l.InsertAfter(2, e1) // Iterate through list and print its contents. for e := l.Front(); e != nil; e = e.Next() { fmt.Println(e.Value) } }
  • 91. container - heap // This example demonstrates an integer heap built using the heap interface. package main import ( "container/heap" "fmt" ) // An IntHeap is a min-heap of ints. type IntHeap []int func (h IntHeap) Len() int { return len(h) } func (h IntHeap) Less(i, j int) bool { return h[i] < h[j] } func (h IntHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] } func (h *IntHeap) Push(x interface{}) { // Push and Pop use pointer receivers because they modify the slice's length, // not just its contents. *h = append(*h, x.(int)) } func (h *IntHeap) Pop() interface{} { old := *h n := len(old) x := old[n-1] *h = old[0 : n-1] return x } // This example inserts several ints into an IntHeap, checks the minimum, // and removes them in order of priority. func main() { h := &IntHeap{2, 1, 5} heap.Init(h) heap.Push(h, 3) fmt.Printf("minimum: %dn", (*h)[0]) for h.Len() > 0 { fmt.Printf("%d ", heap.Pop(h)) } }
  • 92. sort • Sort 함수는 sort.Interface가 구현된 것만 정렬가능 • sort.Interface는 Len, Less, Swap의 3개 메서드 필요. type Interface interface { // Len is the number of elements in the collection. Len() int // Less reports whether the element with // index i should sort before the element with index j. Less(i, j int) bool // Swap swaps the elements with indexes i and j. Swap(i, j int) }
  • 93. sort type Person struct { Name string Age int } type ByName []Person func (this ByName) Len() int { return len(this) } func (this ByName) Less(i, j int) bool { return this[i].Name < this[j].Name } func (this ByName) Swap(i, j int) { this[i], this[j] = this[j], this[i] } func main() { kids := []Person{ {"Jill",9}, {"Jack",10}, } sort.Sort(ByName(kids)) fmt.Println(kids) }
  • 94. hash type Hash interface { // Write (via the embedded io.Writer interface) adds more data to the running hash. // It never returns an error. io.Writer // Sum appends the current hash to b and returns the resulting slice. // It does not change the underlying hash state. Sum(b []byte) []byte // Reset resets the Hash to its initial state. Reset() // Size returns the number of bytes Sum will return. Size() int // BlockSize returns the hash's underlying block size. // The Write method must be able to accept any amount // of data, but it may operate more efficiently if all writes // are a multiple of the block size. BlockSize() int } type Hash32 interface { Hash Sum32() uint32 } type Hash64 interface { Hash Sum64() uint64 }
  • 95. hash - 비암호화 • 종류 : adler32, crc32, crc64, fnv package main import ( "fmt" "hash/crc32" ) func main() { h := crc32.NewIEEE() h.Write([]byte("test")) v := h.Sum32() fmt.Println(v) }  3632233996
  • 96. crypto – 암호화해시 • 종류 : aes, cipher, des, dsa, ecdsa, elliptic, hmac, md5, rand, rc4, rsa, sha1, sha256, sha512, subtle, tls, 509 package main import ( "crypto/sha1" "fmt" "io" ) func main() { h := sha1.New() io.WriteString(h, "His money is twice tainted:") io.WriteString(h, " 'taint yours and 'taint mine.") fmt.Printf("% x", h.Sum(nil)) }
  • 97. net • Go는 아래에 대해 Portable 인터페이스를 제공 – Network I/O – TCP/IP – UDP – Domain name resolution – Unix domain socket type Listener interface { // Accept waits for and returns the next connection to the listener. Accept() (c Conn, err error) // Close closes the listener. // Any blocked Accept operations will be unblocked and return errors. Close() error // Addr returns the listener's network address. Addr() Addr }
  • 98. net //////////////////// Client 간단버전 ////////////////// conn, err := net.Dial("tcp", "google.com:80") if err != nil { // handle error } fmt.Fprintf(conn, "GET / HTTP/1.0rnrn") status, err := bufio.NewReader(conn).ReadString('n') // ... ////////////////// Server 간단버전 ////////////////// ln, err := net.Listen("tcp", ":8080") if err != nil { // handle error } for { conn, err := ln.Accept() if err != nil { // handle error } go handleConnection(conn) }
  • 99. net ////////////// Echo 서버 //////////// package main import ( "io”; "log”; "net" ) func main() { // Listen on TCP port 2000 on all interfaces. l, err := net.Listen("tcp", ":2000") if err != nil { log.Fatal(err) } defer l.Close() for { // Wait for a connection. conn, err := l.Accept() if err != nil { log.Fatal(err) } // Handle the connection in a new goroutine. // The loop then returns to accepting, s o that // multiple connections may be served concurrently. go func(c net.Conn) { // Echo all incoming data. io.Copy(c, c) // Shut down the connection. c.Close() }(conn) } } $ telnet localhost 2000 I love Go  입력 I love Go  출력
  • 100. net/http package main import ("net/http" ; "io") func hello(res http.ResponseWriter, req *http.Request) { res.Header().Set( "Content-Type", "text/html", ) io.WriteString( res, `<doctype html> <html> <head><title>Hello World</title></head> <body>Hello World!</body> </html>`, ) } func main() { http.HandleFunc("/hello", hello) http.ListenAndServe(":9000", nil) } http://localhost:9000/hello HandleFunc는 URL 라우팅(/hello) 처리를 담당해요
  • 101. net/rpc package main import ( "fmt” ; "net”; "net/rpc" ) type Server struct {} func (this *Server) Negate(i int64, reply *int64) error { *reply = -i return nil } func server() { rpc.Register(new(Server)) ln, err := net.Listen("tcp", ":9999") if err != nil { fmt.Println(err) return } for { c, err := ln.Accept() if err != nil { continue } go rpc.ServeConn(c) } } func client() { c, err := rpc.Dial("tcp", "127.0.0.1:9999") if err != nil { fmt.Println(err) return } var result int64 err = c.Call("Server.Negate", int64(999), &result) if err != nil { fmt.Println(err) } else { fmt.Println("Server.Negate(999) =", result) } } func main() { go server() go client() var input string fmt.Scanln(&input) }
  • 102. flag (명령줄 파싱) • 명령줄 플래그(-로 시작)를 flag.String(), Bool(), Int() 등을 사용하여 파싱 – flag.Int(플래그명, 기본값, 설명메시지) – flag.IntVar(입력변수주소, 플래그명, 기본값, 설명메시지) – 방법1 import "flag" var ip = flag.Int("flagname", 1234, "help message for flagname”) – 방법2 var flagvar int func init() { flag.IntVar(&flagvar, "flagname", 1234, "help message for flagname") } • 플래그가 아닌 일반파라미터는 flag.Args()를 통해 받을 수 있으며 []string 형으로 리턴된다. var args []string = flag.Args()
  • 103. flag (명령줄 파싱) package main import ( "flag" "fmt" ) var species = flag.String("species", "gopher", "the species we are studying") var gopherType string func init() { const ( defaultGopher = "pocket" usage = "the variety of gopher" ) flag.StringVar(&gopherType, "gopher_type", defaultGopher, usage) flag.StringVar(&gopherType, "g", defaultGopher, usage+" (shorthand)") } func main() { flag.Parse() fmt.Println("species=", *species, "ngopherType=", gopherType) var args []string = flag.Args() fmt.Println("Args=", args) }
  • 104. flag (명령줄 파싱) $ ./hello species= gopher gopherType= pocket Args= [] $ ./hello -h Usage of ./hello: -g="pocket": the variety of gopher (shorthand) -gopher_type="pocket": the variety of gopher -species="gopher": the species we are studying $ ./hello -species=oce -g=fastcat species= oce gopherType= fastcat Args= [] $ ./hello -species=oce -gopher_type=fastcat  위 결과와 동일 species= oce gopherType= fastcat Args= [] $ ./hello -species=”oce fastcat” world war 2 species= oce fastcat gopherType= pocket Args= [world war 2]
  • 105. sync type Cond func NewCond(l Locker) *Cond func (c *Cond) Broadcast() func (c *Cond) Signal() func (c *Cond) Wait() type Locker type Mutex func (m *Mutex) Lock() func (m *Mutex) Unlock() type Once func (o *Once) Do(f func()) type Pool func (p *Pool) Get() interface{} func (p *Pool) Put(x interface{}) type RWMutex func (rw *RWMutex) Lock() func (rw *RWMutex) RLock() func (rw *RWMutex) RLocker() Locker func (rw *RWMutex) RUnlock() func (rw *RWMutex) Unlock() type WaitGroup func (wg *WaitGroup) Add(delta int) func (wg *WaitGroup) Done() func (wg *WaitGroup) Wait() 더 많은 정보는 여기있어요 https://golang.org/pkg/sync/
  • 106. sync/Mutex package main import ( "fmt”; "sync”; "time" ) func main() { m := new(sync.Mutex) for i := 0; i < 10; i++ { go func(i int) { m.Lock() fmt.Println(i, "start") time.Sleep(time.Second) fmt.Println(i, "end") m.Unlock() }(i) } var input string fmt.Scanln(&input) } 실행결과 0 start 0 end 1 start 1 end 2 start 2 end 3 start 3 end 4 start 4 end 5 start 5 end 6 start 6 end 7 start 7 end 8 start 8 end 9 start 9 end
  • 107. sync/Once package main import ( "fmt”; "sync" ) func main() { var once sync.Once onceBody := func() { fmt.Println("Only once") } done := make(chan bool) for i := 0; i < 10; i++ { go func() { once.Do(onceBody) done <- true }() } for i := 0; i < 10; i++ { <-done } }  결과 : Only once
  • 108. sync/WaitGroup var wg sync.WaitGroup var urls = []string{ "http://www.golang.org/", "http://www.google.com/", "http://www.somestupidname.com/", } for _, url := range urls { // Increment the WaitGroup counter. wg.Add(1) // Launch a goroutine to fetch the URL. go func(url string) { // Decrement the counter when the goroutine completes. defer wg.Done() // Fetch the URL. http.Get(url) }(url) } // Wait for all HTTP fetches to complete. wg.Wait()
  • 109. Go 의 동기화 스타일 type Work struct { x, y, z int assigned, done bool } type WorkSet struct { mu sync.Mutex work []*Work } type Work struct { x, y, z int } func worker(in <-chan *Work, out chan<- *Work) { for w := range in { w.z = w.x * w.y // do some work... out <- w } } func main() { in, out := make(chan *Work), make(chan *Work) for i := 0; i < 10; i++ { go worker(in, out) } go sendLotsOfWork(in) receiveLotsOfResults(out) } 메모리공유를 통한 통신이나 공유데이터를 보호하기 위한 Lock이 필요없다. 전통적인 접근 Go 스타일
  • 110. time 정의 : func Sleep(d Duration) 샘플 : time.Sleep(100 * time.Millisecond) 정의 : func (t Time) Sub(u Time) Duration 샘플 : t0 := time.Now() expensiveCall() t1 := time.Now() mt.Printf("The call took %v to run.n", t1.Sub(t0))  3m56s 정의 : func Date(year int, month Month, day, hour, min, sec, nsec int, loc *Location) Time 샘플 : t := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC) 정의 : func (t Time) Format(layout string) string 샘플 : const layout = "Jan 2, 2006 at 3:04pm (MST)" t := time.Date(2009, time.November, 10, 15, 0, 0, 0, time.Local) fmt.Println(t.Format(layout)) 정의 : func Parse(layout, value string) (Time, error) 샘플 : const longForm = "Jan 2, 2006 at 3:04pm (MST)" t, _ := time.Parse(longForm, "Feb 3, 2013 at 7:54pm (PST)") Go 에는 Java의 yyyyMMdd 같은 형식이 없어요.
  • 111. regexp 정의 : func MatchString(pattern string, s string) (matched bool, err error) 샘플 : matched, err := regexp.MatchString("foo.*", "seafood") 정의 : func MustCompile(str string) *Regexp 샘플 : var re = regexp.MustCompile(`^[a-z]+[[0-9]+]$`) 정의 : func (re *Regexp) MatchString(s string) bool 샘플 : fmt.Println(re.MatchString("adam[23]")) 정의 : func (re *Regexp) FindAllString(s string, n int) []string 샘플 : fmt.Println(re.FindAllString("paranormal", -1)) 정의 : func (re *Regexp) ReplaceAllString(src, repl string) string 샘플 : fmt.Println(re.ReplaceAllString("-ab-axxb-", "T"))
  • 112. database age := 27 rows, err := db.Query("SELECT name FROM users WHERE age=?", age) if err != nil { log.Fatal(err) } defer rows.Close() for rows.Next() { var name string if err := rows.Scan(&name); err != nil { log.Fatal(err) } fmt.Printf("%s is %dn", name, age) } if err := rows.Err(); err != nil { log.Fatal(err) } https://github.com/golang/go/wiki/SQLDrivers
  • 113. database - drivers • MySQL: https://github.com/ziutek/mymysql [*] • MySQL: https://github.com/go-sql-driver/mysql/ [*] • Postgres (pure Go): https://github.com/lib/pq [*] • Oracle: https://github.com/mattn/go-oci8 • MS SQL Server (pure go): https://github.com/denisenkom/go-mssqldb 그 외의 드라이버는 여기를 참조하세요. https://github.com/golang/go/wiki/SQLDrivers
  • 114. database - mysql package main import ( "os" "github.com/ziutek/mymysql/mysql" _ "github.com/ziutek/mymysql/native" // Native engine // _ "github.com/ziutek/mymysql/thrsafe" // Thread safe engine ) func main() { db := mysql.New("tcp", "", "127.0.0.1:3306", user, pass, dbname) err := db.Connect() if err != nil { panic(err) } rows, res, err := db.Query("select * from X where id > %d", 20) if err != nil { panic(err) } https://github.com/ziutek/mymysql for _, row := range rows { for _, col := range row { if col == nil { // col has NULL value } else { // Do something with text in col (type []byte) } } // You can get specific value from a row val1 := row[1].([]byte) // You can use it directly if conversion isn't needed os.Stdout.Write(val1) // You can get converted value number := row.Int(0) // Zero value str := row.Str(1) // First value bignum := row.MustUint(2) // Second value // You may get values by column name first := res.Map("FirstColumn") second := res.Map("SecondColumn") val1, val2 := row.Int(first), row.Str(second) } }
  • 115. log package main import ( "bytes" "fmt" "log" ) func main() { var buf bytes.Buffer logger := log.New(&buf, "logger: ", log.Lshortfile) logger.Print("Hello, log file!") fmt.Print(&buf) }  logger: main.go:12: Hello, log file!
  • 116. log - level • 로그레벨에 따라 로깅하는 패키지는 기본 SDK에 없다. • https://github.com/jcelliott/lumber • 콘솔로거 log := lumber.NewConsoleLogger(lumber.WARN) • 파일로거 log := lumber.NewFileLogger("filename.log", lumber.INFO, lumber.ROTATE, 5000, 9, 100) • 파일로거 (rotate) log := lumber.NewRotateLogger("filename.log", 5000, 9) • 사용법 log.Trace("the %s log level", "lowest") log.Debug("") log.Info("the default log level") log.Warn("") log.Error("") log.Fatal("the %s log level", "highest") • 로그앞에 prefix 붙이기 log.Prefix("MYAPP")