[Go] Go력 1년의 현재, fmt.Prin을 들여다보기 ()
개시하다
고 쓰기 시작한 지 1년이 지났다.
나는 처음 쓴 날
fmt.Println("Hello World")
이 그립다.Hello World
와 프린트할 일은 거의 없지만 fmt.Println
항상 당신의 보살핌을 받았습니다.모처럼의 기회인 만큼 이 기회를 틈타 천천히
fmt.Println
설치를 살펴보고 싶다.fmt.Println("Hello World")
Println
func Println(a ...interface{}) (n int, err error) {
return Fprintln(os.Stdout, a...)
}
매개 변수 형식은 임의의 인터페이스 {}이고, 반환 값의 형식은 int와 error입니다.
잘 되돌아오는 값이 있겠지.현재 반환 값을 변수에 대입하지 않았습니다.
함수의 내용은 한 줄만 있고 호출 중입니다
Fprintln
.읽기
Println
는 읽기Fprintln
와 같다는 것이다.Fprintln
의 첫 번째 매개 변수에 전달os.Stdout
.os.Stdout
는 os
가방에 성명된 변수입니다.var (
Stdin = NewFile(uintptr(syscall.Stdin), "/dev/stdin")
Stdout = NewFile(uintptr(syscall.Stdout), "/dev/stdout")
Stderr = NewFile(uintptr(syscall.Stderr), "/dev/stderr")
)
Println
의 시작은 os.Stdout
에 대입된 *os.File
유형의 값이 가지고 있는 Write
방법에 따라 진행되었다.Fprintln
func Fprintln(w io.Writer, a ...interface{}) (n int, err error) {
p := newPrinter()
p.doPrintln(a)
n, err = w.Write(p.buf)
p.free()
return
}
어디 보자
Fprintln
.*pp
프린터 상태를 관리하는 구조체를 초기화하거나 호출 방법을 사용하거나 버퍼 메모리를 작성합니다.Write
의 반환값으로 인해 Println
과 Fprintln
의 반환값은 Write
의 반환값이다.솔직히 여기까지는 만족하지만, 좀 더 깊이 들어가고 싶어요.
newPrinter
func newPrinter() *pp {
p := ppFree.Get().(*pp)
p.panicking = false
p.erroring = false
p.wrapErrs = false
p.fmt.init(&p.buf)
return p
}
초기화 함수
newPrinter
를 살펴보자.ppFree.Get().(*pp)
에서 제작*pp
형의 값을 만들고 초기 값을 제작 값의 필드에 삽입한다.필드의 대입은 물론이고 신경을 많이 썼다
ppFree.Get().(*pp)
.익숙하지 않은 함수라고 하고 반환값을
*pp
형으로 나눈다.이 보기 싫은 함수는 도대체 누구일까.
ppFree
var ppFree = sync.Pool{
New: func() interface{} { return new(pp) },
}
눈에 거슬리는 함수
Get
는 구조체의 방법이다.필드
sync.Pool
에 초기화 후New
가 구조로 돌아가는 함수를 넣었기 때문에 *pp
구조sync.Pool
방법에서Get
라고 할 수 있다.New
뭐야.sync.Pool
type Pool struct {
noCopy noCopy
local unsafe.Pointer // local fixed-size per-P pool, actual type is [P]poolLocal
localSize uintptr // size of the local array
victim unsafe.Pointer // local from previous cycle
victimSize uintptr // size of victims array
// New optionally specifies a function to generate
// a value when Get would otherwise return nil.
// It may not be changed concurrently with calls to Get.
New func() interface{}
}
댓글이 많아서 열심히 읽었는데 잘 모르겠어요.
나는 축적된 오라리의 책을 읽고 기술 보도도 읽었지만 부드러웠다.
어쨌든 현재로는...
sync.Pool
이기 때문에 구조나 절편 등을 효과적으로 처리하는 연못interface{}
에서 수영장에서 대상을 얻다Get
New
객체를 풀로 반환Put
와 Get
는 골프장 안전Put
구조체를 반복해서 사용할 수 있습니다!재활용으로 확보한 pp
입니다!그런가요?[]byte
의 일은 좀 더 잘 조사해야 하지만 분위기만 이해하면 계속 읽을 수 있다.한마디로 수영장 취득 대상
sync.Pool
에서 발견Get
된 호칭이다.free
func (p *pp) free() {
// Proper usage of a sync.Pool requires each entry to have approximately
// the same memory cost. To obtain this property when the stored type
// contains a variably-sized buffer, we add a hard limit on the maximum buffer
// to place back in the pool.
//
// See https://golang.org/issue/23199
if cap(p.buf) > 64<<10 {
return
}
p.buf = p.buf[:0]
p.arg = nil
p.value = reflect.Value{}
p.wrappedErr = nil
ppFree.Put(p)
}
수영장
New
으로 반환되며Put
구조체의 방법pp
내에서 불린다.큰 거
free
면 수영장에 안 갈 것 같아.doPrintln
func (p *pp) doPrintln(a []interface{}) {
for argNum, arg := range a {
if argNum > 0 {
p.buf.writeByte(' ')
}
p.printArg(arg, 'v')
}
p.buf.writeByte('\n')
}
그럼 마지막으로 보시죠
[]byte
.구조체의 방법
doPrintln
을 호출하여 pp
의 매개 변수로 임의의 값을 주고 버퍼에 순서대로 기록합니다.형식 지정 하위 항목은 항상 지정됩니다
printArg
.또한 ln이기 때문에 매개 변수의 마지막 요소를 쓴 후에 쓴다
Println
.총결산
%v
\n
에서 처리된 내용을 간략하게 요약하면수영장
fmt.Println
에서 구조체를 얻다(수영장에 대기 중fmt.Fprintln
이 없으면 새로 만든 구조체로 돌아간다)↓
출력할 값을 버퍼에 쓰기
↓
쓰기 버퍼 값을 출력 위치에 쓰기
↓
패브릭을 풀로 반환
pp
이런 흐름.특별히 해결하고 싶은 목적은 없고, 표준 포장의 원본 코드를 읽는 것은 오락이다.
설치가 잘 안 돼서 읽을 때 디테일한 부분을 쉽게 읽을 수 있지만 이 코드들을 따라잡았으면 좋겠어요.
또 알다
pp
가 첫 수확이었다.표준 포장의 코드링은 기술과 흥미를 높이는 동시에 계속하고 싶습니다.
읽어주셔서 감사합니다.
참고 자료
Reference
이 문제에 관하여([Go] Go력 1년의 현재, fmt.Prin을 들여다보기 ()), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://zenn.dev/shinshin/articles/b499b76e08d2f1텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)