Golang - 네가 모르는 10가지

13342 단어 Go
본문 번역은 문장에서 번역한 것으로, 여기에 감사를 드립니다.

10 things you (probably) don’t know about golang


익명 구조(Anonymous structs)


템플릿 데이터

data := struct {
    Title string
    Users []*User //  User  , 
} {
    title,
    USERS,
}
err := tmpl.Execute(w, data)

(Cheaper and safer than using map [string]interface {})가 확실히 이해가 안 되네요. 무슨 뜻이죠?

내장형 잠금(Embedded Lock)

var hits struct{
    sync.Mutex   // ,( )
    n int
}
hits.Lock()  // ( C++ )
hits.n++
hits.Unlock()

Nested structs 내포된 구조


Decoding deeply nested JSON data

{"data" : {"children" : [
 {"data" : {
  "title" : "The Go homepage",
  "url" : "http://golang.org/"}}
  ,
  ...
  ]}}
type Item struct{
    Titel  string
    URL    string
}
type Response struct{  //  Structs   Json  , 
    Data struct {
        Children []struct {
            Data Item
        }
    }
}
  golang  json  ,  JSON  。

Command-line godoc 명령행 godoc

% godoc sync Mutex //  godoc  ,sync , Mutex 

디스플레이 값은 다음과 같습니다.
type Mutex struct { //contains filtered or unexported fields } A Mutex is a mutual exclusion lock. Mutexes can be created as part of other structures; the zero value for a Mutex is an unlocked mutex.
func (m *Mutex) Lock() Lock locks m. If the lock is already in use, the calling goroutine blocks until the mutex is available.
func (m *Mutex) Unlock() Unlock unlocks m. It is a run-time error if m is not locked on entry to Unlock.
A locked Mutex is not associated with a particular goroutine. It is
allowed for one goroutine to lock a Mutex and then arrange for another
goroutine to unlock it.

godc -src는 Golang의 소스 코드를 직접 표시할 수 있습니다.

% godoc -src sync Mutex

다음과 같이 표시됩니다.
//A Mutex is a mutual exclusion lock.//Mutexes can be created as part of other structures//the zero value for a Mutex is an unlocked mutex. type Mutex struct { state int32 sema uint32 }//Local per-P Pool appendix. type poolLocal struct { Mutex//Protects shared. //contains filtered or unexported fields }
보시면 unexported state가 표시됩니다!우리가 원본 코드에 대해 깊이 있는 탐색을 진행하는 데 편리하다.

Mock out the file system(파일 시스템 패러디)


현재 패키지가 있습니다. 이 패키지는 파일 시스템과 협업을 해야 합니다. 하지만 테스트에 진정한 디스크를 사용하고 싶지 않습니다. 어떻게 해야 합니까?
var fs fileSystem = osFS{}

type fileSystem interface {  // 
    Open(name string) (file, error)
    Stat(name string) (os.fileInfo, error)
}

type file interface { //    file 
    io.Closer
    io.Reader
    io.ReaderAt
    io.Seeker
    Stat() (os.FileInfo, error)
}

type osFs struct{} // osFs  ,  fileSystem  。
func (osFs) Open(name string) (file, error)  // , file 
func (osFs) Stat(name string) (os.FileInfo, error) 

Method expression

type T struct{}  //  T
func (T) Foo(string) {fmt.Println(s)}  // T 
//fn  , 
//  : fn   func(T, string)
// Foo  : func (T) Foo(string)  
var fn func(T, sring) = T.Foo  

os/exec의 실제 예:
func (c *Cmd) stdin() (f *os.File, error)
func (c *Cmd) stdout() (f *os.File, error)
func (c *Cmd) stderr() (f *os.File, error)

type F func(*cmd) (*os.File, error)
for _, setupFd := range []F{(*Cmd).stdin, (*Cmd).stdout, (*Cmd).stderr} { // 
    fd, err := steupFd(c)
    if err != nil {
        c.closeDescriptors(c.closeAfterStart)
        c.closeDescriptors(c.closeAfterWait)
        return err
    }
    c.childFiles = append(c.childFiles, fd)
}

Send and receive on the same channel

package main

import "fmt"

var battle = make(chan string) //  channel  

func warrior(name string, done chan struct{}) {
    // : select ,  channel ?
    select {
    case oppoent := //battle  
        fmt.Printf("%s beat %s
"
, name, oppoent) case battle //battle // I lost } done struct{}{} } func main() { done := make(chan struct{}) langs := []string{"Go", "C", "C++", "Java", "Perl", "Python"} for _, s := range langs { go warrior(s, done) // Goroutine } for _ = range langs { // Goroutine , ? } }

프로그램이 여러 번 실행되고 출력이 같지 않습니다: 처음 실행:
Java beat C++ Go beat C Perl beat Python
두 번째 실행:
Python beat Perl Go beat C C++ beat Java
지금 문제는: 1.같은 Select에서 두 개 혹은 두 개 이상의case 문장에서 같은 채널이 데이터를 수신하면 어떻게 됩니까?2. 같은 채널이 동시에 데이터를 보내면 어떻게 될까?3. 같은 채널(발송과 수신) 데이터는 어떻게 되나요?자발적으로 수확하는 현상이 있을까요?
자신의 추측: 1.만약 두 개의 채널이 동시에 데이터를 발송한다면 랜덤으로 하나의 채널을 선택하여 데이터를 발송할 것이다.만약 두 개의 채널이 동시에 데이터를 수신한다면, 랜덤으로 하나의 채널을 선택하여 데이터를 수신할 것이다.3. 같은 채널(발송과 수신) 데이터는 자발적인 수신 현상을 일으키지 않고 이 채널에 막힌다.상술한 예에 대해 구체적인 Select는 어떻게 일을 하는지 잘 모르겠다.(고수의 가르침을 구함)

Close로 브로드캐스트하는 Using close to broadcast

package main

import (
    "fmt"
    "math/rand"  // 
    "time"
)

func waiter(i int, block, done chan struct{}) {
    time.Sleep(time.Duration(rand.Intn(3000)) * time.Millisecond)
    fmt.Println(i, "waiting...")
    //  goroutine   block ,  close(block)
    fmt.Println(i, "done!")
    done struct{}{}
}

func main() {
    block, done := make(chan struct{}), make(chan struct{})

    for i := 0; i < 4; i++ {
        go waiter(i, block, done)
    }

    time.Sleep(5 * time.Second)
    close(block)  // ,  block   ( )
    for i := 0; i < 4; i++ {
        
3 waiting...
2 waiting...
1 waiting...
0 waiting...
3 done!
2 done!
1 done!
0 done!
  • 우선 모든 고루틴을 막는다"
  • main의 Goroutine가close(block)를 진행할 때 모든 Block이 다시 막히지 않는다
  • close()로 한 번 방송한 셈
  • NIl channel in select

    func worker(i int, ch chan work, quit chan struct{}) {
        for { 
            select {
            case w :=if quit == nil {  //  channel == nil ?
                    w.Refuse();
                    fmt.Println("worker", i, "refused",w)
                    break;
                }
                w.Do();
            case "worker", i, "quiting")
                quit = nilnil)
            }
        }
    }
    
    
    func main() {
        ch, quit := make(chan work), make(chan struct{})
        go makeWork(ch)
        for i := 0; i < 4; i++ {
            go worker(i, ch, quit)
        }
        time.Sleep(5 * time.Second)
        close(quit)
        time.Sleep(2 * time.Second)
    }

    상술한 코드는 약간 잘 모르는 부분이 있다.1.close(quit)가 되면,quit는 정상적인 채널에서nil로 바뀌나요?(아닐 것이다) 2.만약 quit가 돌아오지 않았을 때, 노동자는 영원히 일을 하고 있을 것이다.3. Qit가 돌아오면 Qit=nil, 그리고 그 다음에 일꾼에게 일을 명령하려면 일꾼은 물러나 그만둔다.

    총결산


    전체적으로 어려운 점은 채널과 struct에 있다.1. 채널의 다양한 이용으로 동기화와 비동기화, 병발 등의 기능을 실현한다.코드에서만 탐색할 수 있습니다.2. 골롱의 메모리 모델에 대해 잘 이해하지 못하고 많은 부분이 불분명하다.나중에 천천히 이해할 수밖에 없어요.

    좋은 웹페이지 즐겨찾기