go 문법
import 문법
import "fmt"
또는
import (
"fmt"
"math"
)
함수선언
func add(x int, y int) int {
return x + y
}
또는
func add(x, y int) int {
return x + y
}
여러개 return
func add(x, y int) (int, int) {
return x, y
}
return 에 이름 붙이기(알아서 x, y 가 return 됨)
func add(x, y int) (x, y int) {
x = x + 1
y = y + 1
return
}
// func(int) int 를 return 하는 함수 adder()
func adder() func(int) int {
sum := 0
return func(x int) int {
sum += x
return sum
}
}
변수선언
const (
cc1 = "hello"
cc2 = "babo"
)
var x, y, z int
var a, b, c int = 1, 2, 3
var p, j bool
var k, l = true, "no"
type Pointer struct {
X, Y int
}
func main() {
aa, bb := true, "hello!" // 함수내에서만 가능
const gogolang = "gogo"
fmt.Println(a, b, c, x, y, z, p, j)
// 배열, slice 라 부른다.
p := []int{2, 3, 5, 7, 11, 13}
fmt.Println(p[0])
fmt.Println("p[1:4] ==", p[1:4])
fmt.Println("p[:3] ==", p[:3])
fmt.Println("p[4:] ==", p[4:])
// 배열 생성, '0' 으로 초기화된다.
arr := make([]int, 5) // len(arr)=5, array item 은 int type
arr2 := make([]int, 0, 5) // len(b)=0, cap(b)=5 , 용량제한
//
//
var m map[string]Pointer
m = make(map[string]Pointer)
m["1stPointer"] = Pointer{ 0, 1}
fmt.Println(m["1stPointer"])
//
//
var mm = map[string]Pointer{
"1stP": Pointer{0,1},
"2ndP": {2,3},
}
//
m2 := make(map[string]int)
m2["mykey"] = 48
delete(m2, "mykey")
v, ok := m2["mykey"] // mykey 가 존재하면 ok 는 true, 존재하지 않으면 ok 는 false
}
}
slice 참고 자료
make 함수
type Job func() jobQueue := make(chan Job, 10) // buffer 가 10 인 channel 만들기 jobQueue := make([]Job, 10) // Job 10개가 들어가는 array 만들기 r := make(<-chan bool) // 읽기 전용 채널 w := make(chan<- []os.FileInfo) // 쓰기 전용 채널 // a channel which: // - you can only write to // - holds another channel as its value c := make(chan<- chan bool) // 아래 "channel 관련" 을 참고하자.
slice / map /chan 을 new 할때 쓴다. slice, map, chan 에 사용할 때, 각각 다른 방식으로 동작한다.
이 녀석이 allocate 하고, initialize 를 해준다. 참고로, 이 make 를 써야하는 slice/map/chan 은 선언(declare) 만 해서는 reference 만 생성된다. 그러니 struct 안에넣을 때는 make() 를 호출 해주는 init 함수등이 따로 필요하다.
channel
ready := make(chan bool)
위와 같은 unbuffered channel은 sender 나 receiver 가 준비가 돼서 communicate 가 될 때까지 block 된다. 그러므로, 이 녀석은 필연적으로 goroutine 과 함께 써야 한다. 왜냐하면, 만약 이 channel 에 대해 read 를 시도하면, 일단 block 되어 버리는데, 이상태에서 이 channel 에 write 를 해줄 방법은 goroutine 등 다른 thread 를 사용하는 수밖에 없기 때문이다.
cap()
len() 은 data 가 얼마나 존재하는지 알려주고, cap() 이라는 것은 array 가 있으면 이 array 가 할당해 놓은 memory size 를 이야기한다.nil
None, null 같은 개념이다.error type
type error interface {
Error() string
}
errors.New 로 error type 의 string 을 만들 수 있다.
func Sqrt(f float64) (float64, error) {
if f < 0 {
return 0, errors.New("math: square root of negative number")
}
// implementation
}
for 문
sum := 0
for i := 0; i < 10; i++ {
sum += i
}
//
j := 0
for j < 10 {
sum += j
}
//
for{
if j < 10 {
sum += j
}
}
//
var arr = []int{1, 2, 4, 8, 16, 32, 64, 128}
func main() {
for i, v := range arr {
fmt.Printf("2**%d = %d\n", i, v)
}
for _, v := range arr {
fmt.Printf(v)
}
for i := range arr {
fmt.Printf(i)
}
}
if, switch 문
if j:= math.Pow(1,2); j < 100 {
fmt.Println(j)
}else{
// j는 if, else 안에서만 사용
fmt.Println(j)
}
import "runtime"
switch os := runtime.GOOS; os {
case "darwin":
fmt.Println("OS X.") // break 가 없어도 자동으로 break 된다.
case os + "_X":
fmt.Println("Linux.")
default:
fmt.Printf("%s.", os)
}
// if--then--else 대용으로 사용하면 된다.
t := time.Now()
switch { // switch true
case t.Hour() < 12:
fmt.Println("Good morning!")
case t.Hour() < 17:
fmt.Println("Good afternoon.")
default:
fmt.Println("Good evening.")
}
기본 자료형
bool
string
int int8 int16 int32 int64
uint uint8 uint16 uint32 uint64 uintptr
byte // uint8의 다른 이름(alias)
rune // int32의 다른 이름(alias)
// 유니코드 코드 포인트 값을 표현합니다.
float32 float64
complex64 complex128
string 참고 소스
구조체 struct
type Point struct {
X int
Y int
}
var (
p = Pointer{1, 2} // has type Vertex
q = &Pointer{1, 2} // has type *Vertex
r = Pointer{X: 1} // Y:0 is implicit
s = Pointer{} // X:0 and Y:0
)
func main() {
p := Point{1, 2} // create
p.X = 4
q := &p // pointer 할당
q.X = 5
fmt.Println(p.Y)
fmt.Println(q.X) // q.X 는 5 가 되고, p.X 도 5가 된다.
//
v := new(Pionter) // new 는 필드를 '0' 으로 초기화 한다.
v.X = 5
var w *Pointer = new(Pointer) // w:= new(Pointer)
w.X = 10
}
go 는 pointer 가 있지만, pointer 연산은 안된다.
class 문법
class 는 없고, struct 에 함수를 추가할 수 있다.(결국 이름 붙이기 나름이긴 하다. ) 여하튼 이때 pointer type 과 일반적인 type 으로 method receiver 를 설정할 수 있다. 자세한 것은 여기를 참고하자.
// modified while the server is running.
type Server struct {
running bool
}
// Peers returns all connected peers.
func (srv *Server) Peers() []*Peer {
var ps []*Peer
select {
// Note: We'd love to put this function into a variable but
// that seems to cause a weird compiler error in some
// environments.
case srv.peerOp <- func(peers map[discover.NodeID]*Peer) {
for _, p := range peers {
ps = append(ps, p)
}
}:
<-srv.peerOpDone
case <-srv.quit:
}
return ps
}
//
// 기존 type 에 함수를 추가, 기본 type 에는 추가할 수 없지만, 아래처럼 새롭게 자신의 type 을 선언하면 된다.
// 그리고 다른 package 에 있는 type 에 추가할 수는 없다.
//
type MyFloat float64
func (f MyFloat) Abs() float64 {
if f < 0 {
return float64(-f)
}
return float64(f)
}
func main() {
f := MyFloat(-math.Sqrt2)
fmt.Println(f.Abs())
}
strconv
string --> inti, err := strconv.Atoi("-42")
s := strconv.Itoa(-42)
interface
변수선언할 때 interface{} type 은 Java 의 object처럼 가장 상위 개념의 type 이라 봐도 좋을 듯 하다.
interface type 으로 variable 을 하나 선언하면,
이 variable 로 모든 interface type 을 받을 수 있고, primitive type 도 받을 수 있기 때문이다.
func main() {
var i interface{} = 3.0
s := i.(float64)
fmt.Println(s)
s, ok := i.(float64)
fmt.Println(s, ok)
f, ok := i.(string)
fmt.Println(f, ok)
f = i.(string) // panic
fmt.Println(f)
}
import "strconv" type Stringer interface { ToString() string } func main() { var a Stringer f := MyFloat(103.22) v := Vertex{3.0, 4.0} a = f // a MyFloat implements Stringer a = &v // a *Vertex implements Stringer a = v // Error: a Vertex, does NOT implement Stringer fmt.Println(a.Abs()) } // MyFloat type MyFloat float64 func (f MyFloat) ToString() string { return strconv.FormatFloat(f, 'f', -1, 64) // infinite precision '-1' , 64 bit } // Vertex type Vertex struct { X, Y float64 } func (v *Vertex) ToString() string { return strconv.Itoa(v.X) }
type assertions
이 때 이 interface 가 가진 child 에 따라 동작을 하도록 하려면, 아래처럼 (type) 과 switch 를 이용할 수 있다.type Stringer interface {
String() string
}
var value interface{} // Value provided by caller.
switch str := value.(type) {
case string:
return str
case Stringer:
return str.String()
}
function pointer
함수를 parameter 로 넘기는 것은 간단하다.func paramFunc(title string) int{ fmt.Println(title) return 1 } func testFuncPointer(fn func(string) int) int{ ret := fn("test") return ret } func main() { testFuncPointer(paramFunc) }
file i/o
import "io/ioutil"
var body = []byte("Test")
ioutil.WriteFile(filename, body, 0600) // 0600 is permission
body, error := ioutil.ReadFile(filename)
defer
이 녀석은 python 의 with 같다. java 의 fianlly 와도 비슷하다. 근데 약간 이름이 부자연스럽긴 하다.아래 코드에서 defer 는 function 이 끝나는 시점에 수행된다. 즉, writeFile 을 하고 난 후에 closeFile 이 실행된다.
func main() {
f := createFile("/tmp/defer.txt")
defer closeFile(f)
writeFile(f)
}
thread
go 에서는 goroutine 으로 불린다. go 뒤에 수행하고 싶은 function 을 넣으면 된다. 그러면 go func 을 한 순간부터 run 이 되는 것이다.go func(){ fmt.Println("this is a thread")}
select
대략적으로 이야기하면, queue 에서 값을 가져와서 어떤 작업을 하는 녀석(예를 들면, dispatcher) 을 만들 때 사용하면 된다.(좀 더 응용해서 어떤 신호를 받을 때 사용하면 된다.)select 가 만약 default 를 가지고 있으면, queue 가 empty 일때 default 가 호출된다. 그리고 default 가 없다면, queue 에 item 이 들어올 때 까지 block 된다.(참고)
type Job func()
type worker struct {
jobChannel chan Job
}
func (w *worker) start() {
// new thread start
go func() {
var job Job
for {
select {
case job = <-w.jobChannel:
job()
}
}
}()
}
예제
package main
import (
"fmt"
"os"
"bufio"
"strings"
"strconv"
)
func main() {
fmt.Println("Hello, 世界")
var caseCount, cPlank int
fmt.Scanf("%d\n", &caseCount)
for i := 0; i<caseCount; i++{
var hlist []int32
fmt.Scanf("%d\n", &cPlank)
reader := bufio.NewReader(os.Stdin)
fmt.Print("Enter text: ")
text, _ := reader.ReadString('\n')
text = strings.TrimRight(text, "\r\n")
// convert string to []int
// "3 2 4" --> [3, 2, 4]
splitStr := strings.Split(text, " ")
for _, s := range splitStr{
pint, err := strconv.ParseInt(s, 10, 64)
if err != nil{
fmt.Print("error")
fmt.Println(err)
}
hlist = append(hlist, int32(pint))
}
fmt.Println(hlist)
}
}
See Also
- A Tour of Go
- Go by Example
- avelino/awesome-go: A curated list of awesome Go frameworks, libraries and software
- Projects · golang/go Wiki
- Learn Go by writing tests – Hello, world : https://github.com/quii/learn-go-with-tests/tree/master/hello-world
댓글 없음:
댓글 쓰기