├── .editorconfig ├── .github ├── ISSUE_TEMPLATE.md └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── .nojekyll ├── 163study-go-master.jpg ├── A20181610.jpg ├── LICENSE ├── Makefile ├── README.md ├── SUMMARY.md ├── appendix ├── appendix-a-trap.md ├── appendix-b-gems.md ├── appendix-c-author.md └── readme.md ├── book.ini ├── cch.png ├── ch1-basic ├── ch1-01-genesis.md ├── ch1-02-hello-revolution.md ├── ch1-03-array-string-and-slice.md ├── ch1-04-func-method-interface.md ├── ch1-05-mem.md ├── ch1-06-goroutine.md ├── ch1-07-error-and-panic.md ├── ch1-08-ext.md └── readme.md ├── ch2-cgo ├── ch2-01-hello-cgo.md ├── ch2-02-basic.md ├── ch2-03-cgo-types.md ├── ch2-04-func.md ├── ch2-05-internal.md ├── ch2-06-qsort.md ├── ch2-07-memory.md ├── ch2-08-class.md ├── ch2-09-static-shared-lib.md ├── ch2-10-link.md ├── ch2-11-ext.md └── readme.md ├── ch3-asm ├── ch3-01-basic.md ├── ch3-02-arch.md ├── ch3-03-const-and-var.md ├── ch3-04-func.md ├── ch3-05-control-flow.md ├── ch3-06-func-again.md ├── ch3-07-hack-asm.md ├── ch3-08-goroutine-id.md ├── ch3-09-debug.md ├── ch3-10-ext.md └── readme.md ├── ch4-rpc ├── ch4-01-rpc-intro.md ├── ch4-02-pb-intro.md ├── ch4-03-netrpc-hack.md ├── ch4-04-grpc.md ├── ch4-05-grpc-hack.md ├── ch4-06-grpc-ext.md ├── ch4-07-pbgo.md ├── ch4-08-grpcurl.md ├── ch4-09-ext.md └── readme.md ├── ch5-web ├── ch5-01-introduction.md ├── ch5-02-router.md ├── ch5-03-middleware.md ├── ch5-04-validator.md ├── ch5-05-database.md ├── ch5-06-ratelimit.md ├── ch5-07-layout-of-web-project.md ├── ch5-08-interface-and-web.md ├── ch5-09-gated-launch.md ├── ch5-10-ext.md └── readme.md ├── ch6-cloud ├── ch6-01-dist-id.md ├── ch6-02-lock.md ├── ch6-03-delay-job.md ├── ch6-04-search-engine.md ├── ch6-05-load-balance.md ├── ch6-06-config.md ├── ch6-07-crawler.md ├── ch6-08-ext.md └── readme.md ├── chaoxi ├── .gitignore └── .keep ├── contributors.json ├── cover-20190714.jpg ├── cover-bak.png ├── cover.jpg ├── cover.png ├── cover_small.jpg ├── css.png ├── doc.go ├── docs ├── .gitignore └── x64_cheatsheet.pdf ├── douban.png ├── errata ├── README.md ├── a.go ├── a_amd64.s └── ch3-12-func-call-frame-01.ditaa.png ├── examples ├── README.md ├── ch1.1 │ └── 1-hello │ │ └── main.go ├── ch1.2 │ ├── 1-hello-b-1972 │ │ └── main.b │ ├── 10-hello-go-200806 │ │ └── hello.go.txt │ ├── 11-hello-go-20080627 │ │ └── hello.go.txt │ ├── 12-hello-go-20080811 │ │ └── hello.go.txt │ ├── 13-hello-go-20081024 │ │ └── hello.go.txt │ ├── 14-hello-go-20090115 │ │ └── hello.go.txt │ ├── 15-hello-go-20091211 │ │ └── hello.go │ ├── 16-hello-go-v2 │ │ └── hello.go │ ├── 2-hello-c-1974 │ │ └── hello-c-01.c │ ├── 3-hello-c-1978 │ │ └── hello-c-02.c │ ├── 4-hello-c-1988 │ │ └── hello-c-03.c │ ├── 5-hello-c-1989 │ │ └── hello-c-04.c │ ├── 6-hello-newsqueak-1989 │ │ └── hello.newsqueak │ ├── 7-prime-newsqueak │ │ └── prime.newsqueak │ ├── 8-hello-alef-1993 │ │ └── hello.alef │ ├── 9-hello-limbo-1995 │ │ └── hello.limbo │ ├── xx-hello-go-asm │ │ ├── hello.go │ │ └── hello_amd64.s │ ├── xx-hello-go-cgo │ │ └── hello.go │ └── xx-hello-go-swig │ │ ├── hello.cc │ │ ├── hello.go │ │ └── hello.swigcxx ├── ch2.1 │ ├── hello-01 │ │ └── main.go │ ├── hello-02 │ │ └── main.go │ ├── hello-03 │ │ ├── hello.c │ │ └── main.go │ ├── hello-04 │ │ └── main.go │ ├── hello-05 │ │ └── main.go │ └── hello-06 │ │ └── main.go ├── ch2.10 │ ├── hello-py │ │ ├── Makefile │ │ ├── gopkg.h │ │ ├── main.go │ │ └── py3-config.go │ └── hello-so │ │ ├── Makefile │ │ ├── _test_so.c │ │ ├── hello.py │ │ ├── main.go │ │ └── say-hello.h ├── ch2.4 │ └── return-go-ptr │ │ └── main.go ├── ch2.5 │ ├── 01-cgo-gen-files │ │ ├── Makefile │ │ ├── _obj │ │ │ ├── _cgo_export.c │ │ │ ├── _cgo_export.h │ │ │ ├── _cgo_flags │ │ │ ├── _cgo_gotypes.go │ │ │ ├── _cgo_main.c │ │ │ ├── hello.cgo1.go │ │ │ ├── hello.cgo2.c │ │ │ ├── main.cgo1.go │ │ │ └── main.cgo2.c │ │ ├── hello.go │ │ ├── main.go │ │ ├── nocgo_1.go │ │ └── nocgo_x.go │ ├── 02-go-call-c-func │ │ ├── Makefile │ │ ├── _obj │ │ │ ├── _cgo_export.c │ │ │ ├── _cgo_export.h │ │ │ ├── _cgo_flags │ │ │ ├── _cgo_gotypes.go │ │ │ ├── _cgo_main.c │ │ │ ├── main.cgo1.go │ │ │ └── main.cgo2.c │ │ └── main.go │ └── 03-c-call-go-func │ │ ├── Makefile │ │ ├── _obj │ │ ├── _cgo_export.c │ │ ├── _cgo_export.h │ │ ├── _cgo_flags │ │ ├── _cgo_gotypes.go │ │ ├── _cgo_main.c │ │ ├── sum.cgo1.go │ │ └── sum.cgo2.c │ │ ├── main.c │ │ ├── sum.go │ │ └── sum.h ├── ch2.6 │ ├── 01-qsort-v1 │ │ ├── Makefile │ │ └── main.c │ ├── 02-qsort-v2 │ │ ├── main.go │ │ ├── qsort.go │ │ ├── qsort_test.go │ │ └── test_helper.go │ ├── 03-qsort-v3 │ │ ├── main.go │ │ ├── sort.go │ │ └── sort_test.go │ └── 04-qsort-v4 │ │ ├── main.go │ │ ├── sort.go │ │ └── sort_test.go ├── ch2.8 │ ├── class-cc2go │ │ ├── main.go │ │ ├── my_buffer.cc │ │ ├── my_buffer.go │ │ ├── my_buffer.h │ │ ├── my_buffer_capi.cc │ │ ├── my_buffer_capi.go │ │ └── my_buffer_capi.h │ └── class-go2cc │ │ ├── goobj.go │ │ ├── main.cc │ │ ├── main.go │ │ ├── persion.go │ │ ├── person.cc │ │ ├── person.h │ │ ├── person_capi.go │ │ └── person_capi.h ├── ch2.9 │ ├── incorrect-dll-api │ │ ├── Makefile │ │ ├── main.go │ │ └── mystring │ │ │ ├── Makefile │ │ │ ├── mystring.c │ │ │ └── mystring.h │ ├── make-clib-dll │ │ ├── Makefile │ │ ├── _test_main.c │ │ ├── main.go │ │ ├── number-win64.def │ │ └── number.h │ ├── make-clib-from-multi-pkg │ │ ├── Makefile │ │ ├── _test_main.c │ │ ├── main.go │ │ ├── main.h │ │ └── number │ │ │ ├── number.go │ │ │ └── number.h │ ├── make-clib-shared │ │ ├── Makefile │ │ ├── _test_main.c │ │ ├── main.go │ │ └── number.h │ ├── make-clib-static │ │ ├── Makefile │ │ ├── _test_main.c │ │ ├── main.go │ │ └── number.h │ ├── plugin │ │ ├── Makefile │ │ ├── main.go │ │ └── plugin.go │ ├── use-clib-shared │ │ ├── Makefile │ │ ├── main.go │ │ └── number │ │ │ ├── Makefile │ │ │ ├── number.c │ │ │ └── number.h │ ├── use-clib-static-v1 │ │ ├── Makefile │ │ ├── main.go │ │ └── number │ │ │ ├── Makefile │ │ │ ├── number.c │ │ │ └── number.h │ └── use-clib-static-v2 │ │ ├── Makefile │ │ ├── main.go │ │ ├── number │ │ ├── Makefile │ │ ├── number.c │ │ └── number.h │ │ └── z_link_number_c.c ├── ch2.x │ ├── hello-swig-v1 │ │ ├── Makefile │ │ ├── hello.cc │ │ ├── hello.swigcxx │ │ ├── hello_test.go │ │ └── runme.go │ ├── hello-swig-v2 │ │ ├── Makefile │ │ ├── hello.cc │ │ ├── hello.go │ │ ├── hello.i │ │ ├── runme.go │ │ └── swig_wrap.cc │ └── hello │ │ ├── .gitignore │ │ ├── Makefile │ │ ├── _obj │ │ ├── _cgo_export.c │ │ ├── _cgo_export.h │ │ ├── _cgo_flags │ │ ├── _cgo_gotypes.go │ │ ├── _cgo_main.c │ │ ├── hello.cgo1.go │ │ └── hello.cgo2.c │ │ └── hello.go ├── ch3.1 │ ├── id-01 │ │ ├── pkg.go │ │ └── runme.go │ ├── id-02 │ │ ├── pkg.go │ │ ├── pkg_amd64.s │ │ └── runme.go │ ├── main-01 │ │ ├── Makefile │ │ ├── main.go │ │ └── main_amd64.s │ ├── str-01 │ │ └── pkg.go │ ├── str-02 │ │ ├── pkg.go │ │ ├── pkg_amd64.s │ │ └── runme.go │ └── str-03 │ │ ├── pkg.go │ │ ├── pkg_amd64.s │ │ └── runme.go ├── ch3.6 │ ├── asm-split │ │ ├── main.go │ │ └── main_amd64.s │ ├── closure-01 │ │ └── main.go │ └── closure-02 │ │ ├── main.go │ │ └── main_amd64.s ├── ch3.8 │ ├── ch3.8-1 │ │ └── main.go │ ├── ch3.8-2 │ │ └── main.go │ ├── ch3.8-3 │ │ └── main.go │ ├── ch3.8-4 │ │ ├── main.go │ │ └── main_amd64.s │ ├── ch3.8-5 │ │ ├── main.go │ │ └── main_amd64.s │ ├── ch3.8-6 │ │ ├── gls │ │ │ ├── gls.go │ │ │ ├── goid.go │ │ │ └── goid_amd64.s │ │ ├── go.mod │ │ └── main.go │ ├── hello-asm │ │ ├── main.go │ │ └── main_amd64.s │ └── hello │ │ └── main.go ├── ch3.x │ ├── add │ │ ├── add.go │ │ ├── add_asm.go │ │ ├── add_asm_amd64.s │ │ ├── add_asm_generic.go │ │ ├── add_test.go │ │ └── runme.go │ ├── binary_search │ │ ├── binary_search.go │ │ ├── binary_search_amd64.s │ │ └── binary_search_test.go │ ├── cfun │ │ ├── main.go │ │ └── vendor │ │ │ └── asmpkg │ │ │ ├── asmpkg.go │ │ │ └── asmpkg_amd64.s │ ├── globalvar │ │ ├── asm_amd64.s │ │ ├── globalvar.go │ │ └── runme.go │ ├── hello │ │ ├── hello.go │ │ ├── hello_amd64.s │ │ └── runme.go │ ├── ifelse │ │ ├── ifelse.go │ │ ├── ifelse_ams_amd64.s │ │ ├── ifelse_test.go │ │ └── runme.go │ ├── instr │ │ ├── bench_test.go │ │ ├── instr.go │ │ └── instr_amd64.s │ ├── loop │ │ ├── loop.go │ │ ├── loop_asm_amd64.s │ │ ├── loop_test.go │ │ └── runme.go │ ├── min │ │ ├── min.go │ │ ├── min_asm_amd64.s │ │ ├── min_test.go │ │ └── runme.go │ ├── slice │ │ ├── runme.go │ │ ├── slice.go │ │ ├── slice_asm_amd64.s │ │ └── slice_test.go │ ├── stackmap │ │ ├── stackmap.go │ │ ├── stackmap_amd64.s │ │ └── stackmap_test.go │ ├── sum │ │ ├── sum.go │ │ ├── sum_amd64.s │ │ └── sum_test.go │ └── vector │ │ ├── sum_amd64.s │ │ ├── vector.go │ │ ├── vector_amd64.s │ │ └── vector_test.go ├── ch4.1 │ ├── hello-client-v1 │ │ └── main.go │ ├── hello-server-v1 │ │ └── main.go │ ├── hello-service-v2 │ │ ├── api │ │ │ └── hello.go │ │ ├── client │ │ │ └── main.go │ │ └── server │ │ │ └── main.go │ └── hello-service-v3 │ │ ├── client │ │ └── main.go │ │ ├── server-on-http │ │ └── main.go │ │ └── server │ │ └── main.go ├── ch4.2 │ ├── hello-server │ │ └── main.go │ ├── hello.pb │ │ ├── Makefile │ │ ├── hello.pb.go │ │ └── hello.proto │ └── protoc-gen-go-netrpc │ │ ├── main.go │ │ └── netprpc.go ├── ch4.3 │ ├── rpc-auth │ │ ├── client │ │ │ └── main.go │ │ ├── main.go │ │ └── server │ │ │ └── main.go │ ├── rpc-context │ │ ├── client │ │ │ └── main.go │ │ └── server │ │ │ └── main.go │ └── rpc-reverse │ │ ├── client │ │ └── main.go │ │ └── server │ │ └── main.go ├── ch4.4 │ ├── 1 │ │ ├── client │ │ │ └── main.go │ │ ├── helloservice │ │ │ ├── hello.pb.go │ │ │ └── hello.proto │ │ └── server │ │ │ └── main.go │ ├── 2 │ │ ├── HelloService │ │ │ ├── hello.pb.go │ │ │ └── hello.proto │ │ ├── client │ │ │ └── main.go │ │ └── server │ │ │ └── main.go │ ├── 3 │ │ ├── clientpub │ │ │ └── main.go │ │ ├── clientsub │ │ │ └── main.go │ │ ├── pubsubservice │ │ │ ├── pubsubservice.pb.go │ │ │ └── pubsubservice.proto │ │ └── server │ │ │ └── main.go │ ├── basic │ │ └── client │ │ │ ├── Makefile │ │ │ ├── hello.pb.go │ │ │ ├── hello.proto │ │ │ └── main.go │ └── grpc-pubsub │ │ ├── clientPub │ │ └── clientPub.go │ │ ├── clientSub │ │ └── clientSub.go │ │ ├── pubsubservice │ │ ├── pubsubservice.pb.go │ │ └── pubsubservice.proto │ │ └── server │ │ └── server.go ├── ch4.5 │ ├── on-web │ │ ├── Makefile │ │ ├── helloworld.pb.go │ │ ├── helloworld.proto │ │ ├── main.go │ │ └── tls-config │ │ │ ├── Makefile │ │ │ ├── server.crt │ │ │ └── server.key │ ├── panic-and-log │ │ ├── Makefile │ │ ├── helloworld.pb.go │ │ ├── helloworld.proto │ │ └── main.go │ ├── rest-and-swagger │ │ └── dummy.txt │ ├── tls │ │ ├── Makefile │ │ ├── helloworld.pb.go │ │ ├── helloworld.proto │ │ ├── main.go │ │ └── tls-config │ │ │ ├── Makefile │ │ │ ├── ca.crt │ │ │ ├── ca.key │ │ │ ├── ca.srl │ │ │ ├── client.crt │ │ │ ├── client.csr │ │ │ ├── client.key │ │ │ ├── server.crt │ │ │ ├── server.csr │ │ │ └── server.key │ └── tok │ │ ├── Makefile │ │ ├── helloworld.pb.go │ │ ├── helloworld.proto │ │ └── main.go ├── ch4.6 │ ├── pb2-default-value │ │ ├── Makefile │ │ ├── helloworld.pb.go │ │ └── helloworld.proto │ ├── rest │ │ ├── Makefile │ │ ├── helloworld.pb.go │ │ ├── helloworld.pb.gw.go │ │ ├── helloworld.proto │ │ ├── helloworld.swagger.json │ │ └── main.go │ └── validators │ │ ├── Makefile │ │ ├── helloworld.pb.go │ │ ├── helloworld.proto │ │ └── helloworld.validator.pb.go └── ch4.7 │ ├── http-router │ └── dummy.txt │ ├── pb-option │ ├── Makefile │ ├── dummy.txt │ ├── helloworld.pb.go │ ├── helloworld.proto │ └── main │ │ └── helloworld.pb.go │ ├── pb-web-frameswork │ └── dummy.txt │ └── plugin-framework │ └── dummy.txt ├── gen_contributors.go ├── go.mod ├── go.sum ├── images ├── Makefile ├── appendix-c-chai2010.jpg ├── by-nc-sa-4.0-88x31.png ├── ch1-1-go-family-tree.png ├── ch1-10-slice-1.ditaa.png ├── ch1-10-slice-1.ditaa.txt ├── ch1-11-init.ditaa.png ├── ch1-11-init.ditaa.txt ├── ch1-12-init.ditaa.png ├── ch1-12-init.ditaa.txt ├── ch1-13-prime-sieve.png ├── ch1-2-go-log4.png ├── ch1-3-go-history.png ├── ch1-4-go-history.png ├── ch1-5-prime-sieve.png ├── ch1-6-alef.png ├── ch1-7-array-4int.ditaa.png ├── ch1-7-array-4int.ditaa.txt ├── ch1-8-string-1.ditaa.png ├── ch1-8-string-1.ditaa.txt ├── ch1-9-string-2.ditaa.png ├── ch1-9-string-2.ditaa.txt ├── ch2-1-x-ptr-to-y-ptr.plantuml ├── ch2-1-x-ptr-to-y-ptr.uml.png ├── ch2-2-int32-to-char-ptr.plantuml ├── ch2-2-int32-to-char-ptr.uml.png ├── ch2-3-x-slice-to-y-slice.plantuml ├── ch2-3-x-slice-to-y-slice.uml.png ├── ch2-4-cgo-generated-files.dot ├── ch2-4-cgo-generated-files.dot.png ├── ch2-5-call-c-sum-v1.plantuml ├── ch2-5-call-c-sum-v1.uml.png ├── ch2-6-call-c-sum-v2.plantuml ├── ch2-6-call-c-sum-v2.uml.png ├── ch3-1-arch-hsm-zero.jpg ├── ch3-10-func-arg-01.ditaa.png ├── ch3-10-func-arg-01.ditaa.txt ├── ch3-11-func-local-var-01.ditaa.png ├── ch3-11-func-local-var-01.ditaa.txt ├── ch3-12-func-call-frame-01.ditaa.png ├── ch3-12-func-call-frame-01.ditaa.txt ├── ch3-13-func-stack-frame-layout-01.ditaa.png ├── ch3-13-func-stack-frame-layout-01.ditaa.txt ├── ch3-2-arch-amd64-01.ditaa.png ├── ch3-2-arch-amd64-01.ditaa.txt ├── ch3-3-arch-amd64-02.ditaa.png ├── ch3-3-arch-amd64-02.ditaa.txt ├── ch3-4-pkg-var-decl-01.ditaa.png ├── ch3-4-pkg-var-decl-01.ditaa.txt ├── ch3-5-ieee754.jpg ├── ch3-6-pkg-var-decl-02.ditaa.png ├── ch3-6-pkg-var-decl-02.ditaa.txt ├── ch3-7-pkg-var-decl-03.ditaa.png ├── ch3-7-pkg-var-decl-03.ditaa.txt ├── ch3-8-func-decl-01.ditaa.png ├── ch3-8-func-decl-01.ditaa.txt ├── ch3-9-func-decl-02.ditaa.png ├── ch3-9-func-decl-02.ditaa.txt ├── ch4-1-grpc-go-stack.png ├── ch4-2-grpc-gateway.png ├── ch5-online-group.png ├── ch5-set-time-line.png ├── ch5-set-time-line_2.png ├── ch5-token-bucket.png ├── ch6-02-radix-get-1.png ├── ch6-02-radix-get-2.png ├── ch6-02-radix-get-3.png ├── ch6-02-radix-get-4.png ├── ch6-02-radix-put.png ├── ch6-02-radix.png ├── ch6-02-trie.png ├── ch6-03-gin_contrib.png ├── ch6-03-middleware_flow.png ├── ch6-04-validate-struct-tree.png ├── ch6-04-validate.jpg ├── ch6-06-leaky-bucket.jpg ├── ch6-08-code-gen-2.png ├── ch6-08-code-gen.png ├── ch6-08-control-flow-2.png ├── ch6-08-control-flow.png ├── ch6-08-controller-logic-dao.png ├── ch6-08-frontend-backend.png ├── ch6-08-plugin-arch.jpg ├── ch6-09-nats-protocol-pub.png ├── ch6-09-nats-protocol-sub.png ├── ch6-ast-dsl.png ├── ch6-binary_tree.png ├── ch6-binlog-sync.png ├── ch6-controller-logic-dao-storage.plantuml ├── ch6-controller-logic-dao-storage.uml.png ├── ch6-data-dist1.png ├── ch6-data-dist2.png ├── ch6-dist-crawler.png ├── ch6-four-branch-tree.png ├── ch6-interface-impl.plantuml ├── ch6-interface-impl.uml.png ├── ch6-posting_list.png ├── ch6-snowflake-easy.png ├── ch6-snowflake.png ├── ch6-snoyflake.png ├── ch6-sync.png ├── ch6-task-sched.png ├── ch6-terms.png ├── ch6-timewheel.png └── github-social.drawio ├── index.md ├── preface-pdf.md ├── preface.md ├── toutiao-318517-small.jpg ├── toutiao-318517.jpg ├── weappCode-qq-ke.jpg ├── weixin-guanggu-coder-logo.png └── weixin-guanggu-coder.jpg /.editorconfig: -------------------------------------------------------------------------------- 1 | # Copyright 2017 . All rights reserved. 2 | # Use of this source code is governed by a Apache 3 | # license that can be found in the LICENSE file. 4 | 5 | # http://editorconfig.org/ 6 | 7 | root = true 8 | 9 | # Unix-style newlines with a newline ending every file 10 | [*] 11 | charset = utf-8 12 | end_of_line = lf 13 | trim_trailing_whitespace = true 14 | insert_final_newline = false 15 | 16 | [*] 17 | indent_style = tab 18 | 19 | [*.{go,proto}] 20 | charset = utf-8 21 | indent_style = tab 22 | 23 | # Matches the exact files either package.json or .travis.yml 24 | [{package.json,.travis.yml}] 25 | indent_style = space 26 | indent_size = 2 27 | 28 | [*.yaml] 29 | indent_style = space 30 | indent_size = 2 31 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 提示:哪一章节的问题,建议如何修改 2 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 提示:解决了什么问题,也可以讲下理由。 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /_book 2 | /book 3 | 4 | *.out* 5 | _zz* 6 | -------------------------------------------------------------------------------- /.nojekyll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/.nojekyll -------------------------------------------------------------------------------- /163study-go-master.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/163study-go-master.jpg -------------------------------------------------------------------------------- /A20181610.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/A20181610.jpg -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 2-Clause License 2 | 3 | Copyright (c) 2017, chai2010 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Copyright 2016 . All rights reserved. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | # 6 | # WaBook: Mini Markdown Book 7 | # https://github.com/wa-lang/wabook 8 | # 9 | 10 | default: 11 | wabook serve 12 | 13 | build: 14 | -rm book 15 | wabook build 16 | -rm book/.gitignore 17 | -rm book/.nojekyll 18 | -rm -rf book/.git 19 | 20 | deploy: 21 | -@make clean 22 | wabook build 23 | -rm book/.gitignore 24 | -rm -rf book/.git 25 | -rm -rf book/examples 26 | 27 | cd book && git init 28 | cd book && git add . 29 | cd book && git commit -m "first commit" 30 | cd book && git branch -M gh-pages 31 | cd book && git remote add origin git@github.com:chai2010/advanced-go-programming-book.git 32 | cd book && git push -f origin gh-pages 33 | 34 | clean: 35 | -rm -rf book 36 | -------------------------------------------------------------------------------- /appendix/appendix-c-author.md: -------------------------------------------------------------------------------- 1 | # 附录C:作者简介 2 | 3 | - 柴树杉(Github [@chai2010](https://github.com/chai2010); Twitter [@chaishushan](https://twitter.com/chaishushan))Go语言代码贡献者,Dart语言和WebAssembly等技术爱好者,著有[《WebAssembly标准入门》](https://github.com/chai2010/awesome-wasm-zh/blob/master/webassembly-primer.md)等书。 4 | 5 | - 曹春晖(Github [@cch123](https://github.com/cch123))在 web 领域工作多年,开源爱好者。对大型网站系统的架构和相关工具的实现很感兴趣,并且有一些研究成果。目前在滴滴平台技术部工作。 6 | 7 | -------------------------------------------------------------------------------- /appendix/readme.md: -------------------------------------------------------------------------------- 1 | # 附录 2 | 3 | 附录部分主要包含量三个部分:第一部分是摘录量一些Go语言常见的坑和解决方案;第二部分是一些有趣的代码片段;第三部分是作者信息。 4 | -------------------------------------------------------------------------------- /book.ini: -------------------------------------------------------------------------------- 1 | # https://giscus.app 2 | 3 | [book] 4 | title = "Go语言高级编程" 5 | authors = ["柴树杉", "曹春晖"] 6 | description = "Go语言高级编程" 7 | language = "zh" 8 | multilingual = false 9 | src = "." 10 | 11 | [build] 12 | build-dir = "book" 13 | 14 | [custom] 15 | content_header = "
" 16 | content_footer = "
" 17 | page_footer = "© 2019-2022 | 柴树杉、曹春晖 保留所有权利" 18 | 19 | [giscus] 20 | enaled = true 21 | data_repo = "chai2010/advanced-go-programming-book" 22 | data_repo_id = "MDEwOlJlcG9zaXRvcnkxMTU4NTc5NTQ=" 23 | data_category = "General" 24 | data_category_id = "DIC_kwDOBufaIs4CAwFi" 25 | 26 | [output.html] 27 | git-repository-url = "https://github.com/chai2010/advanced-go-programming-book" 28 | edit-url-template = "https://github.com/chai2010/advanced-go-programming-book/edit/master/{path}" 29 | git-repository-icon = "fa-github" 30 | -------------------------------------------------------------------------------- /cch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/cch.png -------------------------------------------------------------------------------- /ch1-basic/ch1-08-ext.md: -------------------------------------------------------------------------------- 1 | ## 1.8 补充说明 2 | 3 | 本书定位是 Go 语言进阶图书,因此读者需要有一定的 Go 语言基础。如果对 Go 语言不太了解,作者推荐通过以下资料开始学习 Go 语言。首先是安装 Go 语言环境,然后通过 `go tool tour` 命令打开“A Tour of Go”教程学习。在学习“A Tour of Go”教程的同时,可以阅读 Go 语言官方团队出版的[《The Go Programming Language》](http://www.gopl.io/)教程。[《The Go Programming Language》](http://www.gopl.io/)在国内 Go 语言社区被称为 Go 语言圣经,它将带你系统地学习 Go 语言。在学习的同时可以尝试用 Go 语言解决一些小问题,如果遇到要查阅 API 的时候可以通过 `godoc` 命令打开自带的文档查询。Go 语言本身不仅仅包含了所有的文档,也包含了所有标准库的实现代码,这是第一手的最权威的 Go 语言资料。我们认为此时你应该已经可以熟练使用 Go 语言了。 4 | -------------------------------------------------------------------------------- /ch1-basic/readme.md: -------------------------------------------------------------------------------- 1 | # 第 1 章 语言基础 2 | 3 | *我不知道,你过去 10 年为什么不快乐。但相信我,抛掉过去的沉重,使用 Go 语言,体会最初的快乐!——469856321* 4 | 5 | *搬砖民工也会建成自己的罗马帝国。——小张* 6 | 7 | --- 8 | 9 | 本章首先简要介绍 Go 语言的发展历史,并较详细地分析了“Hello World”程序在各个祖先语言中演化过程。然后,对以数组、字符串和切片为代表的基础结构,对以函数、方法和接口所体现的面向过程和鸭子对象的编程,以及 Go 语言特有的并发编程模型和错误处理哲学做了简单介绍。最后,针对 macOS、Windows、Linux 几个主流的开发平台,推荐了几个较友好的 Go 语言编辑器和集成开发环境,因为好的工具可以极大地提高我们的效率。 10 | -------------------------------------------------------------------------------- /ch2-cgo/ch2-11-ext.md: -------------------------------------------------------------------------------- 1 | ## 2.11 补充说明 2 | 3 | CGO 是 C 语言和 Go 语言混合编程的技术,因此要想熟练地使用 CGO 需要了解这两门语言。C 语言推荐两本书:第一本是 C 语言之父编写的《C 程序设计语言》;第二本是讲述 C 语言模块化编程的《C 语言接口与实现: 创建可重用软件的技术》。Go 语言推荐官方出版的《The Go Programming Language》和 Go 语言自带的全部文档和全部代码。 4 | 5 | 为何要花费巨大的精力学习 CGO 是一个问题。任何技术和语言都有它自身的优点和不足,Go 语言不是银弹,它无法解决全部问题。而通过 CGO 可以继承 C/C++ 将近半个世纪的软件遗产,通过 CGO 可以用 Go 给其它系统写 C 接口的共享库,通过 CGO 技术可以让 Go 语言编写的代码可以很好地融入现有的软件生态——而现在的软件正式建立在 C/C++ 语言之上的。因此说 CGO 是一个保底的后备技术,它是 Go 的一个重量级的替补技术,值得任何一个严肃的 Go 语言开发人员学习。 6 | 7 | -------------------------------------------------------------------------------- /ch2-cgo/readme.md: -------------------------------------------------------------------------------- 1 | # 第 2 章 CGO 编程 2 | 3 | *过去的经验往往是走向未来的枷锁,因为在过气技术中投入的沉没成本会阻碍人们拥抱新技术。——chai2010* 4 | 5 | *曾经一度因未能习得 C++ 令人眼花缭乱的新标准而痛苦不已;Go 语言 “少既是多” 大道至简的理念让我重拾信心,寻回了久违的编程乐趣。——Ending* 6 | 7 | C/C++ 经过几十年的发展,已经积累了庞大的软件资产,它们很多久经考验而且性能已经足够优化。Go 语言必须能够站在 C/C++ 这个巨人的肩膀之上,有了海量的 C/C++ 软件资产兜底之后,我们才可以放心愉快地用 Go 语言编程。C 语言作为一个通用语言,很多库会选择提供一个 C 兼容的 API,然后用其他不同的编程语言实现。Go 语言通过自带的一个叫 CGO 的工具来支持 C 语言函数调用,同时我们可以用 Go 语言导出 C 动态库接口给其它语言使用。本章主要讨论 CGO 编程中涉及的一些问题。 8 | -------------------------------------------------------------------------------- /ch3-asm/ch3-10-ext.md: -------------------------------------------------------------------------------- 1 | ## 3.10 补充说明 2 | 3 | 如果是纯粹学习汇编语言,则可以从《深入理解程序设计:使用 Linux 汇编语言》开始,该书讲述了如何以 C 语言的思维实现汇编程序。如果是学习 X86 汇编,则可以从《汇编语言:基于 x86 处理器》开始,然后再结合《现代 x86 汇编语言程序设计》学习 AVX 等高级汇编指令的使用。 4 | 5 | Go 汇编语言的官方文档非常匮乏。其中 “A Quick Guide to Go's Assembler” 是唯一的一篇系统讲述 Go 汇编语言的官方文章,该文章中又引入了另外两篇 Plan9 的文档:A Manual for the Plan 9 assembler 和 Plan 9 C Compilers。Plan9 的两篇文档分别讲述了汇编语言以及和汇编有关联的 C 语言编译器的细节。看过这几篇文档之后会对 Go 汇编语言有了一些模糊的概念,剩下的就是在实战中通过代码学习了。 6 | 7 | Go 语言的编译器和汇编器都带了一个 `-S` 参数,可以查看生成的最终目标代码。通过对比目标代码和原始的 Go 语言或 Go 汇编语言代码的差异可以加深对底层实现的理解。同时 Go 语言连接器的实现代码也包含了很多相关的信息。Go 汇编语言是依托 Go 语言的语言,因此理解 Go 语言的工作原理是也是必要的。比较重要的部分是 Go 语言 runtime 和 reflect 包的实现原理。如果读者了解 CGO 技术,那么对 Go 汇编语言的学习也是一个巨大的帮助。最后是要了解 syscall 包是如何实现系统调用的。 8 | 9 | 得益于 Go 语言的设计,Go 汇编语言的优势也非常明显:跨操作系统、不同 CPU 之间的用法也非常相似、支持 C 语言预处理器、支持模块。同时 Go 汇编语言也存在很多不足:它不是一个独立的语言,底层需要依赖 Go 语言甚至操作系统;很多高级特性很难通过手工汇编完成。虽然 Go 语言官方尽量保持 Go 汇编语言简单,但是汇编语言是一个比较大的话题,大到足以写一本 Go 汇编语言的教程。本章的目的是让大家对 Go 汇编语言简单入门,在看到底层汇编代码的时候不会一头雾水,在某些遇到性能受限制的场合能够通过 Go 汇编突破限制。 10 | 11 | -------------------------------------------------------------------------------- /ch3-asm/readme.md: -------------------------------------------------------------------------------- 1 | # 第 3 章 Go 汇编语言 2 | 3 | *能跑就行,不行加机器。——rfyiamcool & 爱学习的孙老板* 4 | 5 | *跟对人,做对事。——Rhichy* 6 | 7 | Go 语言中很多设计思想和工具都是传承自 Plan9 操作系统,Go 汇编语言也是基于 Plan9 汇编演化而来。根据 Rob Pike 的介绍,大神 Ken Thompson 在 1986 年为 Plan9 系统编写的 C 语言编译器输出的汇编伪代码就是 Plan9 汇编的前身。所谓的 Plan9 汇编语言只是便于以手工方式书写该 C 语言编译器输出的汇编伪代码而已。 8 | 9 | 无论高级语言如何发展,作为最接近 CPU 的汇编语言的地位依然是无法彻底被替代的。只有通过汇编语言才能彻底挖掘 CPU 芯片的全部功能,因此操作系统的引导过程必须要依赖汇编语言的帮助。只有通过汇编语言才能彻底榨干 CPU 芯片的性能,因此很多底层的加密解密等对性能敏感的算法会考虑通过汇编语言进行性能优化。 10 | 11 | 对于每一个严肃的 Gopher,Go 汇编语言都是一个不可忽视的技术。因为哪怕只懂一点点汇编,也便于更好地理解计算机原理,也更容易理解 Go 语言中动态栈、接口等高级特性的实现原理。而且掌握了 Go 汇编语言之后,你将重新站在编程语言鄙视链的顶端,不用担心再被任何其它所谓的高级编程语言用户鄙视。 12 | 13 | 本章我们将以 AMD64 为主要开发环境,简单地探讨 Go 汇编语言的基础用法。 14 | 15 | -------------------------------------------------------------------------------- /ch4-rpc/ch4-09-ext.md: -------------------------------------------------------------------------------- 1 | ## 4.9 补充说明 2 | 3 | 目前专门讲述 RPC 的图书比较少。目前 Protobuf 和 gRPC 的官网都提供了详细的参考资料和例子。本章重点讲述了 Go 标准库的 RPC 和基于 Protobuf 衍生的 gRPC 框架,同时也简单展示了如何自己定制一个 RPC 框架。之所以聚焦在这几个有限的主题,是因为这几个技术都是 Go 语言团队官方在进行维护,和 Go 语言契合也最为默契。不过 RPC 依然是一个庞大的主题,足以单独成书。目前开源世界也有很多富有特色的 RPC 框架,还有针对分布式系统进行深度定制的 RPC 系统,用户可以根据自己实际需求选择合适的工具。 4 | -------------------------------------------------------------------------------- /ch4-rpc/readme.md: -------------------------------------------------------------------------------- 1 | # 第 4 章 RPC 和 Protobuf 2 | 3 | *学习编程,重要的是什么?多练、多看、多实践!跨语言学习,掌握基础语法和语言的特性之后,实战,效率来的最快!——khlipeng* 4 | 5 | RPC 是远程过程调用的缩写(Remote Procedure Call),通俗地说就是调用远处的一个函数。远处到底有多远呢?可能是同一个文件内的不同函数,也可能是同一个机器的另一个进程的函数,还可能是远在火星好奇号上面的某个秘密方法。因为 RPC 涉及的函数可能非常之远,远到它们之间说着完全不同的语言,语言就成了两边的沟通障碍。而 Protobuf 因为支持多种不同的语言(甚至不支持的语言也可以扩展支持),其本身特性也非常方便描述服务的接口(也就是方法列表),因此非常适合作为 RPC 世界的接口交流语言。本章将讨论 RPC 的基本用法,如何针对不同场景设计自己的 RPC 服务,以及围绕 Protobuf 构造的更为庞大的 RPC 生态。 6 | -------------------------------------------------------------------------------- /ch5-web/ch5-10-ext.md: -------------------------------------------------------------------------------- 1 | # 5.10 补充说明 2 | 3 | 现代的软件工程是离不开 Web 的,广义地来讲,Web 甚至可以不用非得基于 http 协议。只要是 CS 或者 BS 架构,都可以认为是 Web 系统。 4 | 5 | 即使是在看起来非常封闭的游戏系统里,因为玩家们与日俱增的联机需求,也同样会涉及到远程通信,这里面也会涉及到很多 Web 方面的技术。 6 | 7 | 所以这个时代,Web 编程是一个程序员所必须接触的知识领域。无论你的目标是成为架构师,是去创业,或是去当技术顾问。Web 方面的知识都会成为你的硬通货。 8 | -------------------------------------------------------------------------------- /ch5-web/readme.md: -------------------------------------------------------------------------------- 1 | # 第 5 章 go 和 Web 2 | 3 | *不管何种编程语言,适合自己的就是最好的。不管何种编程语言,能稳定实现业务逻辑的就是最好的。世间编程语言千千万,世间程序猿万万千,能做到深入理解并应用的就是最好的。——kenrong* 4 | 5 | 本章将会阐述 Go 在 Web 开发方面的现状,并以几个典型的开源 Web 框架为例,带大家深入 Web 框架本身的执行流程。 6 | 7 | 同时会介绍现代企业级 Web 开发面临的一些问题,以及在 Go 中如何面对,并解决这些问题。 8 | 9 | -------------------------------------------------------------------------------- /ch6-cloud/ch6-08-ext.md: -------------------------------------------------------------------------------- 1 | # 6.8 补充说明 2 | 3 | 分布式是很大的领域,本章中的介绍只能算是对领域的管中窥豹。因为大型系统流量大,并发高,所以往往很多朴素的方案会变得难以满足需求。人们为了解决大型系统场景中的各种问题,而开发出了各式各样的分布式系统。有些系统非常简单,比如本章中介绍的分布式 id 生成器,而有一些系统则可能非常复杂,比如本章中的分布式搜索引擎(当然,本章中提到的 es 不是 Go 实现)。 4 | 5 | 无论简单的或是复杂的系统,都会在特定的场景中体现出它们重要的价值,希望读者朋友可以多多接触开源,积累自己的工具箱,从而站在巨人们的肩膀之上。 6 | -------------------------------------------------------------------------------- /ch6-cloud/readme.md: -------------------------------------------------------------------------------- 1 | # 第 6 章 分布式系统 2 | 3 | *被别人指出问题时,别管别人能不能做到,看别人说的对不对,然后完善自己。别人能不能做到是别人的事情,自己能不能做到关系到自己能否发展的更好。——hustlihaifeng* 4 | 5 | Go 语言号称是互联网时代的 C 语言。现在的互联网系统已经不是以前的一个主机搞定一切的时代,互联网时代的后台服务由大量的分布式系统构成,任何单一后台服务器节点的故障并不会导致整个系统的停机。同时以阿里云、腾讯云为代表的云厂商崛起标志着云时代的到来,在云时代分布式编程将成为一个基本技能。而基于 Go 语言构建的 Docker、K8s 等系统推动了云时代的提前到来。 6 | 7 | 对于已经比较完善的分布式系统,我们会简单讲讲怎么通过使用它们来提高我们的工作效率。对于没有现成解决方案的系统,我们会按照自己的业务需求提出解决方案。 8 | -------------------------------------------------------------------------------- /chaoxi/.gitignore: -------------------------------------------------------------------------------- 1 | !*.pdf 2 | -------------------------------------------------------------------------------- /chaoxi/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/chaoxi/.keep -------------------------------------------------------------------------------- /cover-20190714.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/cover-20190714.jpg -------------------------------------------------------------------------------- /cover-bak.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/cover-bak.png -------------------------------------------------------------------------------- /cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/cover.jpg -------------------------------------------------------------------------------- /cover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/cover.png -------------------------------------------------------------------------------- /cover_small.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/cover_small.jpg -------------------------------------------------------------------------------- /css.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/css.png -------------------------------------------------------------------------------- /doc.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 . All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // 6 | // 《Go语言高级编程》 开源图书 - by chai2010 7 | // 8 | // https://github.com/chai2010/advanced-go-programming-book 9 | // 10 | package gobook 11 | -------------------------------------------------------------------------------- /docs/.gitignore: -------------------------------------------------------------------------------- 1 | !x64_cheatsheet.pdf 2 | -------------------------------------------------------------------------------- /docs/x64_cheatsheet.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/docs/x64_cheatsheet.pdf -------------------------------------------------------------------------------- /douban.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/douban.png -------------------------------------------------------------------------------- /errata/a.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | func main() { 8 | fmt.Println("Hello, playground", LoopAdd(100, 1, 1)) 9 | } 10 | 11 | func LoopAdd(cnt, v0, step int) int -------------------------------------------------------------------------------- /errata/a_amd64.s: -------------------------------------------------------------------------------- 1 | #include "textflag.h" 2 | 3 | // func LoopAdd(cnt, v0, step int) int 4 | TEXT ·LoopAdd(SB), NOSPLIT, $0-32 5 | MOVQ $0, BX // result 6 | MOVQ cnt+0(FP), AX // cnt 7 | MOVQ v0+8(FP), DI // vi = v0 8 | MOVQ step+16(FP), CX // step 9 | 10 | LOOP_BEGIN: 11 | MOVQ $0, DX // i 12 | 13 | LOOP_IF: 14 | CMPQ DX, AX // compare i, cnt 15 | JL LOOP_BODY // if i < cnt: goto LOOP_BODY 16 | JMP LOOP_END 17 | 18 | LOOP_BODY: 19 | ADDQ DI, BX // result += vi 20 | ADDQ CX, DI // vi += step 21 | ADDQ $1, DX // i++ 22 | JMP LOOP_IF 23 | 24 | LOOP_END: 25 | 26 | MOVQ BX, ret+24(FP) // return result 27 | RET 28 | -------------------------------------------------------------------------------- /errata/ch3-12-func-call-frame-01.ditaa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/errata/ch3-12-func-call-frame-01.ditaa.png -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | ## goproxy代理服务 2 | 3 | ``` 4 | $ export GOPROXY=https://athens.azurefd.net 5 | ``` 6 | 7 | - https://github.com/gomods/athens/releases 8 | - https://athens.azurefd.net 9 | - https://docs.gomods.io 10 | -------------------------------------------------------------------------------- /examples/ch1.1/1-hello/main.go: -------------------------------------------------------------------------------- 1 | // go run chai2010.cn/gobook/examples/ch1.1/1-hello 2 | 3 | package main 4 | 5 | import "fmt" 6 | 7 | func main() { 8 | fmt.Println("你好, 世界!") 9 | } 10 | -------------------------------------------------------------------------------- /examples/ch1.2/1-hello-b-1972/main.b: -------------------------------------------------------------------------------- 1 | main() { 2 | extrn a, b, c; 3 | putchar(a); putchar(b); putchar(c); 4 | putchar('!*n'); 5 | } 6 | a 'hell'; 7 | b 'o, w'; 8 | c 'orld'; 9 | -------------------------------------------------------------------------------- /examples/ch1.2/10-hello-go-200806/hello.go.txt: -------------------------------------------------------------------------------- 1 | // +build ignore 2 | 3 | package main 4 | 5 | func main() int { 6 | print "hello, world\n"; 7 | return 0; 8 | } 9 | -------------------------------------------------------------------------------- /examples/ch1.2/11-hello-go-20080627/hello.go.txt: -------------------------------------------------------------------------------- 1 | // +build ignore 2 | 3 | package main 4 | 5 | func main() { 6 | print "hello, world\n"; 7 | } 8 | -------------------------------------------------------------------------------- /examples/ch1.2/12-hello-go-20080811/hello.go.txt: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | func main() { 4 | print("hello, world\n"); 5 | } 6 | -------------------------------------------------------------------------------- /examples/ch1.2/13-hello-go-20081024/hello.go.txt: -------------------------------------------------------------------------------- 1 | // +build ignore 2 | 3 | package main 4 | 5 | import "fmt" 6 | 7 | func main() { 8 | fmt.printf("hello, world\n"); 9 | } 10 | -------------------------------------------------------------------------------- /examples/ch1.2/14-hello-go-20090115/hello.go.txt: -------------------------------------------------------------------------------- 1 | // +build ignore 2 | 3 | package main 4 | 5 | import "fmt" 6 | 7 | func main() { 8 | fmt.Printf("hello, world\n"); 9 | } 10 | -------------------------------------------------------------------------------- /examples/ch1.2/15-hello-go-20091211/hello.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Printf("hello, world\n") 7 | } 8 | -------------------------------------------------------------------------------- /examples/ch1.2/16-hello-go-v2/hello.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | "log" 9 | "net/http" 10 | "time" 11 | ) 12 | 13 | func main() { 14 | fmt.Println("Please visit http://127.0.0.1:12345/") 15 | http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) { 16 | s := fmt.Sprintf("你好, 世界! -- Time: %s", time.Now().String()) 17 | fmt.Fprintf(w, "%v\n", s) 18 | log.Printf("%v\n", s) 19 | }) 20 | if err := http.ListenAndServe(":12345", nil); err != nil { 21 | log.Fatal("ListenAndServe: ", err) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /examples/ch1.2/2-hello-c-1974/hello-c-01.c: -------------------------------------------------------------------------------- 1 | main() 2 | { 3 | printf("hello, world"); 4 | } 5 | -------------------------------------------------------------------------------- /examples/ch1.2/3-hello-c-1978/hello-c-02.c: -------------------------------------------------------------------------------- 1 | main() 2 | { 3 | printf("hello, world\n"); 4 | } 5 | -------------------------------------------------------------------------------- /examples/ch1.2/4-hello-c-1988/hello-c-03.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | main() 4 | { 5 | printf("hello, world\n"); 6 | } 7 | -------------------------------------------------------------------------------- /examples/ch1.2/5-hello-c-1989/hello-c-04.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | main(void) 4 | { 5 | printf("hello, world\n"); 6 | } 7 | -------------------------------------------------------------------------------- /examples/ch1.2/6-hello-newsqueak-1989/hello.newsqueak: -------------------------------------------------------------------------------- 1 | print("Hello,", "World", "\n"); 2 | -------------------------------------------------------------------------------- /examples/ch1.2/7-prime-newsqueak/prime.newsqueak: -------------------------------------------------------------------------------- 1 | // 向管道输出从2开始的自然数序列 2 | counter := prog(c:chan of int) { 3 | i := 2; 4 | for(;;) { 5 | c <-= i++; 6 | } 7 | }; 8 | 9 | // 针对listen管道获取的数列,过滤掉是prime倍数的数 10 | // 新的序列输出到send管道 11 | filter := prog(prime:int, listen, send:chan of int) { 12 | i:int; 13 | for(;;) { 14 | if((i = <-listen)%prime) { 15 | send <-= i; 16 | } 17 | } 18 | }; 19 | 20 | // 主函数 21 | // 每个管道第一个流出的数必然是素数 22 | // 然后基于这个新的素数构建新的素数过滤器 23 | sieve := prog() of chan of int { 24 | c := mk(chan of int); 25 | begin counter(c); 26 | prime := mk(chan of int); 27 | begin prog(){ 28 | p:int; 29 | newc:chan of int; 30 | for(;;){ 31 | prime <-= p =<- c; 32 | newc = mk(); 33 | begin filter(p, c, newc); 34 | c = newc; 35 | } 36 | }(); 37 | become prime; 38 | }; 39 | 40 | // 启动素数筛 41 | prime := sieve(); 42 | -------------------------------------------------------------------------------- /examples/ch1.2/8-hello-alef-1993/hello.alef: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void receive(chan(byte*) c) { 4 | byte *s; 5 | s = <- c; 6 | print("%s\n", s); 7 | terminate(nil); 8 | } 9 | 10 | void main(void) { 11 | chan(byte*) c; 12 | alloc c; 13 | proc receive(c); 14 | task receive(c); 15 | c <- = "hello proc or task"; 16 | c <- = "hello proc or task"; 17 | print("done\n"); 18 | terminate(nil); 19 | } 20 | -------------------------------------------------------------------------------- /examples/ch1.2/9-hello-limbo-1995/hello.limbo: -------------------------------------------------------------------------------- 1 | implement Hello; 2 | 3 | include "sys.m"; sys: Sys; 4 | include "draw.m"; 5 | 6 | Hello: module 7 | { 8 | init: fn(ctxt: ref Draw->Context, args: list of string); 9 | }; 10 | 11 | init(ctxt: ref Draw->Context, args: list of string) 12 | { 13 | sys = load Sys Sys->PATH; 14 | sys->print("hello, world\n"); 15 | } 16 | -------------------------------------------------------------------------------- /examples/ch1.2/xx-hello-go-asm/hello.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | package main 5 | 6 | func main() 7 | -------------------------------------------------------------------------------- /examples/ch1.2/xx-hello-go-asm/hello_amd64.s: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | #include "textflag.h" 5 | #include "funcdata.h" 6 | 7 | // "Hello World!\n" 8 | DATA text<>+0(SB)/8,$"Hello Wo" 9 | DATA text<>+8(SB)/8,$"rld!\n" 10 | GLOBL text<>(SB),NOPTR,$16 11 | 12 | // func main() 13 | TEXT ·main(SB), $16-0 14 | NO_LOCAL_POINTERS 15 | MOVQ $text<>+0(SB), AX 16 | MOVQ AX, (SP) 17 | MOVQ $16, 8(SP) 18 | CALL runtime·printstring(SB) 19 | RET 20 | -------------------------------------------------------------------------------- /examples/ch1.2/xx-hello-go-cgo/hello.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | package main 5 | 6 | // #include 7 | // #include 8 | import "C" 9 | import "unsafe" 10 | 11 | func main() { 12 | msg := C.CString("Hello, World!\n") 13 | defer C.free(unsafe.Pointer(msg)) 14 | 15 | C.fputs(msg, C.stdout) 16 | } 17 | -------------------------------------------------------------------------------- /examples/ch1.2/xx-hello-go-swig/hello.cc: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | #include 5 | 6 | void SayHello() { 7 | std::cout << "Hello, World!" << std::endl; 8 | } 9 | -------------------------------------------------------------------------------- /examples/ch1.2/xx-hello-go-swig/hello.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // +build ignore 5 | 6 | package main 7 | 8 | import ( 9 | hello "." 10 | ) 11 | 12 | func main() { 13 | hello.SayHello() 14 | } 15 | -------------------------------------------------------------------------------- /examples/ch1.2/xx-hello-go-swig/hello.swigcxx: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | %module main 5 | 6 | %inline %{ 7 | extern void SayHello(); 8 | %} 9 | -------------------------------------------------------------------------------- /examples/ch2.1/hello-01/main.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | package main 5 | 6 | //#include 7 | import "C" 8 | 9 | func main() { 10 | C.puts(C.CString("Hello, World\n")) 11 | } 12 | -------------------------------------------------------------------------------- /examples/ch2.1/hello-02/main.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | package main 5 | 6 | /* 7 | #include 8 | 9 | static void SayHello(const char* s) { 10 | puts(s); 11 | } 12 | */ 13 | import "C" 14 | 15 | func main() { 16 | C.SayHello(C.CString("Hello, World\n")) 17 | } 18 | -------------------------------------------------------------------------------- /examples/ch2.1/hello-03/hello.c: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | #include 5 | 6 | void SayHello(const char* s) { 7 | puts(s); 8 | } 9 | -------------------------------------------------------------------------------- /examples/ch2.1/hello-03/main.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | package main 5 | 6 | //void SayHello(const char* s); 7 | import "C" 8 | 9 | func main() { 10 | C.SayHello(C.CString("Hello, World\n")) 11 | } 12 | -------------------------------------------------------------------------------- /examples/ch2.1/hello-04/main.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | package main 5 | 6 | /* 7 | #include 8 | 9 | void cgoPuts(char* s); 10 | 11 | static void SayHello(const char* s) { 12 | cgoPuts((char*)(s)); 13 | } 14 | */ 15 | import "C" 16 | import "fmt" 17 | 18 | func main() { 19 | C.SayHello(C.CString("Hello, World\n")) 20 | } 21 | 22 | //export cgoPuts 23 | func cgoPuts(s *C.char) { 24 | fmt.Print(C.GoString(s)) 25 | } 26 | -------------------------------------------------------------------------------- /examples/ch2.1/hello-05/main.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | package main 5 | 6 | //void SayHello(char* s); 7 | import "C" 8 | 9 | import ( 10 | "fmt" 11 | ) 12 | 13 | func main() { 14 | C.SayHello(C.CString("Hello, World\n")) 15 | } 16 | 17 | //export SayHello 18 | func SayHello(s *C.char) { 19 | fmt.Print(C.GoString(s)) 20 | } 21 | -------------------------------------------------------------------------------- /examples/ch2.1/hello-06/main.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // +build go1.10 5 | 6 | package main 7 | 8 | //void SayHello(_GoString_ s); 9 | import "C" 10 | 11 | import ( 12 | "fmt" 13 | ) 14 | 15 | func main() { 16 | C.SayHello("Hello, World\n") 17 | C.SayHello("") 18 | } 19 | 20 | //export SayHello 21 | func SayHello(s string) { 22 | fmt.Println(int(C._GoStringLen(s))) 23 | fmt.Print(s) 24 | } 25 | -------------------------------------------------------------------------------- /examples/ch2.10/hello-py/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright © 2017 ChaiShushan . 2 | # License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | default: 5 | go build -o py3-config.out py3-config.go 6 | PKG_CONFIG=./py3-config.out go build -buildmode=c-shared -o gopkg.so main.go 7 | -rm py3-config.out 8 | python3 -c 'import gopkg; print(gopkg.sum(1, 2))' 9 | 10 | clean: 11 | -rm *.so 12 | -------------------------------------------------------------------------------- /examples/ch2.10/hello-py/main.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | package main 5 | 6 | /* 7 | // macOS: 8 | #cgo darwin pkg-config: python3 9 | 10 | // linux 11 | #cgo linux pkg-config: python3 12 | 13 | // windows 14 | // should generate libpython3.a from python3.lib 15 | 16 | #define Py_LIMITED_API 17 | #include 18 | 19 | extern PyObject* PyInit_gopkg(); 20 | extern PyObject* Py_gopkg_sum(PyObject *, PyObject *); 21 | 22 | static int cgo_PyArg_ParseTuple_ii(PyObject *arg, int *a, int *b) { 23 | return PyArg_ParseTuple(arg, "ii", a, b); 24 | } 25 | 26 | static PyObject* cgo_PyInit_gopkg(void) { 27 | static PyMethodDef methods[] = { 28 | {"sum", Py_gopkg_sum, METH_VARARGS, "Add two numbers."}, 29 | {NULL, NULL, 0, NULL}, 30 | }; 31 | static struct PyModuleDef module = { 32 | PyModuleDef_HEAD_INIT, "gopkg", NULL, -1, methods, 33 | }; 34 | return PyModule_Create(&module); 35 | } 36 | */ 37 | import "C" 38 | 39 | func main() {} 40 | 41 | //export PyInit_gopkg 42 | func PyInit_gopkg() *C.PyObject { 43 | return C.cgo_PyInit_gopkg() 44 | } 45 | 46 | //export Py_gopkg_sum 47 | func Py_gopkg_sum(self, args *C.PyObject) *C.PyObject { 48 | var a, b C.int 49 | if C.cgo_PyArg_ParseTuple_ii(args, &a, &b) == 0 { 50 | return nil 51 | } 52 | return C.PyLong_FromLong(C.long(a + b)) 53 | } 54 | -------------------------------------------------------------------------------- /examples/ch2.10/hello-py/py3-config.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // +build ignore 5 | // +build darwin 6 | 7 | // fix python3-config for cgo build 8 | 9 | package main 10 | 11 | import ( 12 | "bytes" 13 | "fmt" 14 | "os" 15 | "os/exec" 16 | ) 17 | 18 | func main() { 19 | for _, s := range os.Args { 20 | if s == "--cflags" { 21 | out, _ := exec.Command("python3-config", "--cflags").CombinedOutput() 22 | out = bytes.Replace(out, []byte("-arch"), []byte{}, -1) 23 | out = bytes.Replace(out, []byte("i386"), []byte{}, -1) 24 | out = bytes.Replace(out, []byte("x86_64"), []byte{}, -1) 25 | fmt.Print(string(out)) 26 | return 27 | } 28 | if s == "--libs" { 29 | out, _ := exec.Command("python3-config", "--ldflags").CombinedOutput() 30 | fmt.Print(string(out)) 31 | return 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /examples/ch2.10/hello-so/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright © 2017 ChaiShushan . 2 | # License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | default: 5 | go build -buildmode=c-shared -o say-hello.so main.go 6 | gcc -Wall _test_so.c ./say-hello.so 7 | ./a.out 8 | 9 | run-py3: 10 | python3 hello.py 11 | 12 | clean: 13 | -rm *.so 14 | -rm *.out 15 | -------------------------------------------------------------------------------- /examples/ch2.10/hello-so/_test_so.c: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | #include "say-hello.h" 5 | #include 6 | 7 | int main() { 8 | SayHello("gopher"); 9 | return 0; 10 | } 11 | -------------------------------------------------------------------------------- /examples/ch2.10/hello-so/hello.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2017 ChaiShushan . 2 | # License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | import ctypes 5 | 6 | libso = ctypes.CDLL("./say-hello.so") 7 | 8 | SayHello = libso.SayHello 9 | SayHello.argtypes = [ctypes.c_char_p] 10 | SayHello.restype = None 11 | 12 | SayHello(ctypes.c_char_p(b"hello")) 13 | -------------------------------------------------------------------------------- /examples/ch2.10/hello-so/main.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | package main 5 | 6 | import "C" 7 | import "fmt" 8 | 9 | func main() {} 10 | 11 | //export SayHello 12 | func SayHello(name *C.char) { 13 | fmt.Printf("hello %s!\n", C.GoString(name)) 14 | } 15 | -------------------------------------------------------------------------------- /examples/ch2.4/return-go-ptr/main.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | package main 5 | 6 | // go run x.go 7 | // GODEBUG=cgocheck=0 go run x.go 8 | 9 | // panic: runtime error: cgo result has Go pointer 10 | 11 | /* 12 | extern int* getGoPtr(); 13 | 14 | static void Main() { 15 | int* p = getGoPtr(); 16 | *p = 42; 17 | } 18 | */ 19 | import "C" 20 | 21 | func main() { 22 | C.Main() 23 | } 24 | 25 | //export getGoPtr 26 | func getGoPtr() *C.int { 27 | return new(C.int) 28 | } 29 | -------------------------------------------------------------------------------- /examples/ch2.5/01-cgo-gen-files/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright © 2017 ChaiShushan . 2 | # License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | default: clean 5 | # ignore nocgo_*.go files 6 | go tool cgo main.go hello.go 7 | 8 | clean: 9 | -rm -rf ./_obj 10 | -------------------------------------------------------------------------------- /examples/ch2.5/01-cgo-gen-files/_obj/_cgo_export.c: -------------------------------------------------------------------------------- 1 | /* Created by cgo - DO NOT EDIT. */ 2 | #include 3 | #include "_cgo_export.h" 4 | 5 | extern void crosscall2(void (*fn)(void *, int, __SIZE_TYPE__), void *, int, __SIZE_TYPE__); 6 | extern __SIZE_TYPE__ _cgo_wait_runtime_init_done(); 7 | extern void _cgo_release_context(__SIZE_TYPE__); 8 | 9 | extern char* _cgo_topofstack(void); 10 | #define CGO_NO_SANITIZE_THREAD 11 | #define _cgo_tsan_acquire() 12 | #define _cgo_tsan_release() 13 | 14 | -------------------------------------------------------------------------------- /examples/ch2.5/01-cgo-gen-files/_obj/_cgo_flags: -------------------------------------------------------------------------------- 1 | _CGO_CFLAGS= 2 | -------------------------------------------------------------------------------- /examples/ch2.5/01-cgo-gen-files/_obj/_cgo_gotypes.go: -------------------------------------------------------------------------------- 1 | // Created by cgo - DO NOT EDIT 2 | 3 | package main 4 | 5 | import "unsafe" 6 | 7 | import _ "runtime/cgo" 8 | 9 | import "syscall" 10 | 11 | var _ syscall.Errno 12 | func _Cgo_ptr(ptr unsafe.Pointer) unsafe.Pointer { return ptr } 13 | 14 | //go:linkname _Cgo_always_false runtime.cgoAlwaysFalse 15 | var _Cgo_always_false bool 16 | //go:linkname _Cgo_use runtime.cgoUse 17 | func _Cgo_use(interface{}) 18 | type _Ctype_void [0]byte 19 | 20 | //go:linkname _cgo_runtime_cgocall runtime.cgocall 21 | func _cgo_runtime_cgocall(unsafe.Pointer, uintptr) int32 22 | 23 | //go:linkname _cgo_runtime_cgocallback runtime.cgocallback 24 | func _cgo_runtime_cgocallback(unsafe.Pointer, unsafe.Pointer, uintptr, uintptr) 25 | 26 | //go:linkname _cgoCheckPointer runtime.cgoCheckPointer 27 | func _cgoCheckPointer(interface{}, ...interface{}) 28 | 29 | //go:linkname _cgoCheckResult runtime.cgoCheckResult 30 | func _cgoCheckResult(interface{}) 31 | 32 | -------------------------------------------------------------------------------- /examples/ch2.5/01-cgo-gen-files/_obj/_cgo_main.c: -------------------------------------------------------------------------------- 1 | int main() { return 0; } 2 | void crosscall2(void(*fn)(void*, int, __SIZE_TYPE__), void *a, int c, __SIZE_TYPE__ ctxt) { } 3 | __SIZE_TYPE__ _cgo_wait_runtime_init_done() { return 0; } 4 | void _cgo_release_context(__SIZE_TYPE__ ctxt) { } 5 | char* _cgo_topofstack(void) { return (char*)0; } 6 | void _cgo_allocate(void *a, int c) { } 7 | void _cgo_panic(void *a, int c) { } 8 | void _cgo_reginit(void) { } 9 | #line 1 "cgo-generated-wrappers" 10 | -------------------------------------------------------------------------------- /examples/ch2.5/01-cgo-gen-files/_obj/hello.cgo1.go: -------------------------------------------------------------------------------- 1 | // Created by cgo - DO NOT EDIT 2 | 3 | //line hello.go:1 4 | // Copyright © 2017 ChaiShushan . 5 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 6 | 7 | package main 8 | 9 | import _ "unsafe" 10 | -------------------------------------------------------------------------------- /examples/ch2.5/01-cgo-gen-files/_obj/main.cgo1.go: -------------------------------------------------------------------------------- 1 | // Created by cgo - DO NOT EDIT 2 | 3 | //line main.go:1 4 | // Copyright © 2017 ChaiShushan . 5 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 6 | 7 | package main 8 | 9 | import _ "unsafe" 10 | 11 | func main() {} 12 | -------------------------------------------------------------------------------- /examples/ch2.5/01-cgo-gen-files/hello.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | package main 5 | 6 | import "C" 7 | -------------------------------------------------------------------------------- /examples/ch2.5/01-cgo-gen-files/main.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | package main 5 | 6 | import "C" 7 | 8 | func main() {} 9 | -------------------------------------------------------------------------------- /examples/ch2.5/01-cgo-gen-files/nocgo_1.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | package main 5 | -------------------------------------------------------------------------------- /examples/ch2.5/01-cgo-gen-files/nocgo_x.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | package main 5 | -------------------------------------------------------------------------------- /examples/ch2.5/02-go-call-c-func/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright © 2017 ChaiShushan . 2 | # License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | default: clean 5 | go tool cgo main.go 6 | go run main.go 7 | 8 | clean: 9 | -rm -rf ./_obj 10 | -------------------------------------------------------------------------------- /examples/ch2.5/02-go-call-c-func/_obj/_cgo_export.c: -------------------------------------------------------------------------------- 1 | /* Created by cgo - DO NOT EDIT. */ 2 | #include 3 | #include "_cgo_export.h" 4 | 5 | extern void crosscall2(void (*fn)(void *, int, __SIZE_TYPE__), void *, int, __SIZE_TYPE__); 6 | extern __SIZE_TYPE__ _cgo_wait_runtime_init_done(); 7 | extern void _cgo_release_context(__SIZE_TYPE__); 8 | 9 | extern char* _cgo_topofstack(void); 10 | #define CGO_NO_SANITIZE_THREAD 11 | #define _cgo_tsan_acquire() 12 | #define _cgo_tsan_release() 13 | 14 | -------------------------------------------------------------------------------- /examples/ch2.5/02-go-call-c-func/_obj/_cgo_flags: -------------------------------------------------------------------------------- 1 | _CGO_CFLAGS= 2 | -------------------------------------------------------------------------------- /examples/ch2.5/02-go-call-c-func/_obj/_cgo_main.c: -------------------------------------------------------------------------------- 1 | int main() { return 0; } 2 | void crosscall2(void(*fn)(void*, int, __SIZE_TYPE__), void *a, int c, __SIZE_TYPE__ ctxt) { } 3 | __SIZE_TYPE__ _cgo_wait_runtime_init_done() { return 0; } 4 | void _cgo_release_context(__SIZE_TYPE__ ctxt) { } 5 | char* _cgo_topofstack(void) { return (char*)0; } 6 | void _cgo_allocate(void *a, int c) { } 7 | void _cgo_panic(void *a, int c) { } 8 | void _cgo_reginit(void) { } 9 | #line 1 "cgo-generated-wrappers" 10 | -------------------------------------------------------------------------------- /examples/ch2.5/02-go-call-c-func/_obj/main.cgo1.go: -------------------------------------------------------------------------------- 1 | // Created by cgo - DO NOT EDIT 2 | 3 | //line main.go:1 4 | // Copyright © 2017 ChaiShushan . 5 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 6 | 7 | package main 8 | 9 | //int sum(int a, int b) { return a+b; } 10 | import _ "unsafe" 11 | 12 | func main() { 13 | println((_Cfunc_sum)(1, 1)) 14 | } 15 | -------------------------------------------------------------------------------- /examples/ch2.5/02-go-call-c-func/main.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | package main 5 | 6 | //int sum(int a, int b) { return a+b; } 7 | import "C" 8 | 9 | func main() { 10 | println(C.sum(1, 1)) 11 | } 12 | -------------------------------------------------------------------------------- /examples/ch2.5/03-c-call-go-func/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright © 2017 ChaiShushan . 2 | # License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | default: 5 | go tool cgo sum.go 6 | go build -buildmode=c-archive -o sum.a sum.go 7 | gcc -o a.out main.c sum.a 8 | ./a.out 9 | 10 | clean: 11 | -rm -rf ./_obj 12 | -rm sum.a sum.h 13 | -rm a.out 14 | 15 | -------------------------------------------------------------------------------- /examples/ch2.5/03-c-call-go-func/_obj/_cgo_export.c: -------------------------------------------------------------------------------- 1 | /* Created by cgo - DO NOT EDIT. */ 2 | #include 3 | #include "_cgo_export.h" 4 | 5 | extern void crosscall2(void (*fn)(void *, int, __SIZE_TYPE__), void *, int, __SIZE_TYPE__); 6 | extern __SIZE_TYPE__ _cgo_wait_runtime_init_done(); 7 | extern void _cgo_release_context(__SIZE_TYPE__); 8 | 9 | extern char* _cgo_topofstack(void); 10 | #define CGO_NO_SANITIZE_THREAD 11 | #define _cgo_tsan_acquire() 12 | #define _cgo_tsan_release() 13 | 14 | extern void _cgoexp_8313eaf44386_sum(void *, int, __SIZE_TYPE__); 15 | 16 | CGO_NO_SANITIZE_THREAD 17 | int sum(int p0, int p1) 18 | { 19 | __SIZE_TYPE__ _cgo_ctxt = _cgo_wait_runtime_init_done(); 20 | struct { 21 | int p0; 22 | int p1; 23 | int r0; 24 | char __pad0[4]; 25 | } __attribute__((__packed__)) a; 26 | a.p0 = p0; 27 | a.p1 = p1; 28 | _cgo_tsan_release(); 29 | crosscall2(_cgoexp_8313eaf44386_sum, &a, 16, _cgo_ctxt); 30 | _cgo_tsan_acquire(); 31 | _cgo_release_context(_cgo_ctxt); 32 | return a.r0; 33 | } 34 | -------------------------------------------------------------------------------- /examples/ch2.5/03-c-call-go-func/_obj/_cgo_flags: -------------------------------------------------------------------------------- 1 | _CGO_CFLAGS= 2 | -------------------------------------------------------------------------------- /examples/ch2.5/03-c-call-go-func/_obj/_cgo_main.c: -------------------------------------------------------------------------------- 1 | int main() { return 0; } 2 | void crosscall2(void(*fn)(void*, int, __SIZE_TYPE__), void *a, int c, __SIZE_TYPE__ ctxt) { } 3 | __SIZE_TYPE__ _cgo_wait_runtime_init_done() { return 0; } 4 | void _cgo_release_context(__SIZE_TYPE__ ctxt) { } 5 | char* _cgo_topofstack(void) { return (char*)0; } 6 | void _cgo_allocate(void *a, int c) { } 7 | void _cgo_panic(void *a, int c) { } 8 | void _cgo_reginit(void) { } 9 | #line 1 "cgo-generated-wrappers" 10 | int _cgoexp_8313eaf44386_sum; 11 | -------------------------------------------------------------------------------- /examples/ch2.5/03-c-call-go-func/_obj/sum.cgo1.go: -------------------------------------------------------------------------------- 1 | // Created by cgo - DO NOT EDIT 2 | 3 | //line sum.go:1 4 | // Copyright © 2017 ChaiShushan . 5 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 6 | 7 | package main 8 | 9 | //int sum(int a, int b); 10 | import _ "unsafe" 11 | 12 | //export sum 13 | func sum(a, b _Ctype_int) _Ctype_int { 14 | return a + b 15 | } 16 | 17 | func main() {} 18 | -------------------------------------------------------------------------------- /examples/ch2.5/03-c-call-go-func/main.c: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | #include 5 | 6 | int main() { 7 | extern int sum(int a, int b); 8 | printf("1+1=%d\n", sum(1, 1)); 9 | return 0; 10 | } 11 | -------------------------------------------------------------------------------- /examples/ch2.5/03-c-call-go-func/sum.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | package main 5 | 6 | //int sum(int a, int b); 7 | import "C" 8 | 9 | //export sum 10 | func sum(a, b C.int) C.int { 11 | return a + b 12 | } 13 | 14 | func main() {} 15 | -------------------------------------------------------------------------------- /examples/ch2.6/01-qsort-v1/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright © 2018 ChaiShushan . 2 | # License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | default: 5 | gcc main.c && ./a.out && rm a.out 6 | 7 | 8 | clean: 9 | -rm a.out 10 | -------------------------------------------------------------------------------- /examples/ch2.6/01-qsort-v1/main.c: -------------------------------------------------------------------------------- 1 | // Copyright © 2018 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | #include 5 | #include 6 | 7 | #define DIM(x) (sizeof(x)/sizeof((x)[0])) 8 | 9 | static int cmp(const void* a, const void* b) { 10 | const int* pa = (int*)a; 11 | const int* pb = (int*)b; 12 | return *pa - *pb; 13 | } 14 | 15 | int main() { 16 | int values[] = { 42, 8, 109, 97, 23, 25 }; 17 | int i; 18 | 19 | qsort(values, DIM(values), sizeof(values[0]), cmp); 20 | 21 | for(i = 0; i < DIM(values); i++) { 22 | printf ("%d ",values[i]); 23 | } 24 | printf("\n"); 25 | 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /examples/ch2.6/02-qsort-v2/main.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2018 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // +build ignore 5 | 6 | package main 7 | 8 | //extern int go_qsort_compare(void* a, void* b); 9 | import "C" 10 | 11 | import ( 12 | "fmt" 13 | "unsafe" 14 | 15 | qsort "." 16 | ) 17 | 18 | func main() { 19 | values := []int32{42, 9, 101, 95, 27, 25} 20 | 21 | qsort.Sort(unsafe.Pointer(&values[0]), 22 | len(values), int(unsafe.Sizeof(values[0])), 23 | qsort.CompareFunc(C.go_qsort_compare), 24 | ) 25 | fmt.Println(values) 26 | } 27 | 28 | //export go_qsort_compare 29 | func go_qsort_compare(a, b unsafe.Pointer) C.int { 30 | pa, pb := (*C.int)(a), (*C.int)(b) 31 | return C.int(*pa - *pb) 32 | } 33 | -------------------------------------------------------------------------------- /examples/ch2.6/02-qsort-v2/qsort.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2018 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | package qsort 5 | 6 | /* 7 | #include 8 | 9 | typedef int (*qsort_cmp_func_t)(const void* a, const void* b); 10 | */ 11 | import "C" 12 | 13 | import "unsafe" 14 | 15 | type CompareFunc C.qsort_cmp_func_t 16 | 17 | func Sort(base unsafe.Pointer, num, size int, cmp CompareFunc) { 18 | C.qsort(base, C.size_t(num), C.size_t(size), C.qsort_cmp_func_t(cmp)) 19 | } 20 | -------------------------------------------------------------------------------- /examples/ch2.6/02-qsort-v2/qsort_test.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2018 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | package qsort 5 | 6 | import ( 7 | "sort" 8 | "testing" 9 | "unsafe" 10 | ) 11 | 12 | func TestSort(t *testing.T) { 13 | values := []int32{42, 9, 101, 95, 27, 25} 14 | 15 | Sort(unsafe.Pointer(&values[0]), 16 | len(values), int(unsafe.Sizeof(values[0])), 17 | t_get_go_qsort_compare(), 18 | ) 19 | 20 | isSorted := sort.SliceIsSorted(values, func(i, j int) bool { 21 | return values[i] < values[j] 22 | }) 23 | if !isSorted { 24 | t.Fatal("should be sorted") 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /examples/ch2.6/02-qsort-v2/test_helper.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2018 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | package qsort 5 | 6 | //extern int t_go_qsort_compare(void* a, void* b); 7 | import "C" 8 | 9 | import ( 10 | "unsafe" 11 | ) 12 | 13 | func t_get_go_qsort_compare() CompareFunc { 14 | return CompareFunc(C.t_go_qsort_compare) 15 | } 16 | 17 | //export t_go_qsort_compare 18 | func t_go_qsort_compare(a, b unsafe.Pointer) C.int { 19 | pa, pb := (*C.int)(a), (*C.int)(b) 20 | return C.int(*pa - *pb) 21 | } 22 | -------------------------------------------------------------------------------- /examples/ch2.6/03-qsort-v3/main.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2018 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // +build ignore 5 | 6 | package main 7 | 8 | import ( 9 | "fmt" 10 | "unsafe" 11 | 12 | qsort "." 13 | ) 14 | 15 | func main() { 16 | values := []int32{42, 9, 101, 95, 27, 25} 17 | 18 | qsort.Sort(unsafe.Pointer(&values[0]), len(values), int(unsafe.Sizeof(values[0])), 19 | func(a, b unsafe.Pointer) int { 20 | pa, pb := (*int32)(a), (*int32)(b) 21 | return int(*pa - *pb) 22 | }, 23 | ) 24 | 25 | fmt.Println(values) 26 | } 27 | -------------------------------------------------------------------------------- /examples/ch2.6/03-qsort-v3/sort.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2018 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | package qsort 5 | 6 | /* 7 | #include 8 | 9 | typedef int (*qsort_cmp_func_t)(const void* a, const void* b); 10 | extern int _cgo_qsort_compare(void* a, void* b); 11 | */ 12 | import "C" 13 | import ( 14 | "sync" 15 | "unsafe" 16 | ) 17 | 18 | var go_qsort_compare_info struct { 19 | fn func(a, b unsafe.Pointer) int 20 | sync.Mutex 21 | } 22 | 23 | //export _cgo_qsort_compare 24 | func _cgo_qsort_compare(a, b unsafe.Pointer) C.int { 25 | return C.int(go_qsort_compare_info.fn(a, b)) 26 | } 27 | 28 | func Sort(base unsafe.Pointer, num, size int, cmp func(a, b unsafe.Pointer) int) { 29 | go_qsort_compare_info.Lock() 30 | defer go_qsort_compare_info.Unlock() 31 | 32 | go_qsort_compare_info.fn = cmp 33 | 34 | C.qsort(base, C.size_t(num), C.size_t(size), 35 | C.qsort_cmp_func_t(C._cgo_qsort_compare), 36 | ) 37 | } 38 | -------------------------------------------------------------------------------- /examples/ch2.6/03-qsort-v3/sort_test.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2018 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | package qsort 5 | 6 | import ( 7 | "sort" 8 | "testing" 9 | "unsafe" 10 | ) 11 | 12 | func TestSort(t *testing.T) { 13 | values := []int32{42, 9, 101, 95, 27, 25} 14 | 15 | Sort(unsafe.Pointer(&values[0]), len(values), int(unsafe.Sizeof(values[0])), 16 | func(a, b unsafe.Pointer) int { 17 | pa, pb := (*int32)(a), (*int32)(b) 18 | return int(*pa - *pb) 19 | }, 20 | ) 21 | 22 | isSorted := sort.SliceIsSorted(values, func(i, j int) bool { 23 | return values[i] < values[j] 24 | }) 25 | if !isSorted { 26 | t.Fatal("should be sorted") 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /examples/ch2.6/04-qsort-v4/main.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2018 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // +build ignore 5 | 6 | package main 7 | 8 | import ( 9 | "fmt" 10 | 11 | qsort "." 12 | ) 13 | 14 | func main() { 15 | values := []int64{42, 9, 101, 95, 27, 25} 16 | 17 | qsort.Slice(values, func(i, j int) bool { 18 | return values[i] < values[j] 19 | }) 20 | 21 | fmt.Println(values) 22 | } 23 | -------------------------------------------------------------------------------- /examples/ch2.6/04-qsort-v4/sort_test.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2018 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | package qsort 5 | 6 | import ( 7 | "sort" 8 | "testing" 9 | ) 10 | 11 | func TestSlice(t *testing.T) { 12 | values := []int32{42, 9, 101, 95, 27, 25} 13 | 14 | Slice(values, func(i, j int) bool { 15 | return values[i] < values[j] 16 | }) 17 | 18 | isSorted := sort.SliceIsSorted(values, func(i, j int) bool { 19 | return values[i] < values[j] 20 | }) 21 | if !isSorted { 22 | t.Fatal("should be sorted") 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /examples/ch2.8/class-cc2go/main.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | package main 5 | 6 | //#include 7 | import "C" 8 | import "unsafe" 9 | 10 | func main() { 11 | buf := NewMyBuffer(1024) 12 | defer buf.Delete() 13 | 14 | copy(buf.Data(), []byte("hello\x00")) 15 | C.puts((*C.char)(unsafe.Pointer(&(buf.Data()[0])))) 16 | } 17 | -------------------------------------------------------------------------------- /examples/ch2.8/class-cc2go/my_buffer.cc: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | #include "./my_buffer.h" 5 | -------------------------------------------------------------------------------- /examples/ch2.8/class-cc2go/my_buffer.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | package main 5 | 6 | import "unsafe" 7 | 8 | type MyBuffer struct { 9 | cptr *cgo_MyBuffer_T 10 | } 11 | 12 | func NewMyBuffer(size int) *MyBuffer { 13 | return &MyBuffer{ 14 | cptr: cgo_NewMyBuffer(size), 15 | } 16 | } 17 | 18 | func (p *MyBuffer) Delete() { 19 | cgo_DeleteMyBuffer(p.cptr) 20 | } 21 | 22 | func (p *MyBuffer) Data() []byte { 23 | data := cgo_MyBuffer_Data(p.cptr) 24 | size := cgo_MyBuffer_Size(p.cptr) 25 | return ((*[1 << 31]byte)(unsafe.Pointer(data)))[0:int(size):int(size)] 26 | } 27 | -------------------------------------------------------------------------------- /examples/ch2.8/class-cc2go/my_buffer.h: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | #include 5 | 6 | struct MyBuffer { 7 | std::string* s_; 8 | 9 | MyBuffer(int size) { 10 | this->s_ = new std::string(size, char('\0')); 11 | } 12 | ~MyBuffer() { 13 | delete this->s_; 14 | } 15 | 16 | int Size() const { 17 | return this->s_->size(); 18 | } 19 | char* Data() { 20 | return (char*)this->s_->data(); 21 | } 22 | }; 23 | -------------------------------------------------------------------------------- /examples/ch2.8/class-cc2go/my_buffer_capi.cc: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | #include "./my_buffer.h" 5 | 6 | extern "C" { 7 | #include "./my_buffer_capi.h" 8 | } 9 | 10 | struct MyBuffer_T: MyBuffer { 11 | MyBuffer_T(int size): MyBuffer(size) {} 12 | ~MyBuffer_T() {} 13 | }; 14 | 15 | MyBuffer_T* NewMyBuffer(int size) { 16 | auto p = new MyBuffer_T(size); 17 | return p; 18 | } 19 | void DeleteMyBuffer(MyBuffer_T* p) { 20 | delete p; 21 | } 22 | 23 | char* MyBuffer_Data(MyBuffer_T* p) { 24 | return p->Data(); 25 | } 26 | int MyBuffer_Size(MyBuffer_T* p) { 27 | return p->Size(); 28 | } 29 | -------------------------------------------------------------------------------- /examples/ch2.8/class-cc2go/my_buffer_capi.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | package main 5 | 6 | /* 7 | #cgo CXXFLAGS: -std=c++11 8 | 9 | #include "my_buffer_capi.h" 10 | */ 11 | import "C" 12 | 13 | type cgo_MyBuffer_T C.MyBuffer_T 14 | 15 | func cgo_NewMyBuffer(size int) *cgo_MyBuffer_T { 16 | p := C.NewMyBuffer(C.int(size)) 17 | return (*cgo_MyBuffer_T)(p) 18 | } 19 | 20 | func cgo_DeleteMyBuffer(p *cgo_MyBuffer_T) { 21 | C.DeleteMyBuffer((*C.MyBuffer_T)(p)) 22 | } 23 | 24 | func cgo_MyBuffer_Data(p *cgo_MyBuffer_T) *C.char { 25 | return C.MyBuffer_Data((*C.MyBuffer_T)(p)) 26 | } 27 | 28 | func cgo_MyBuffer_Size(p *cgo_MyBuffer_T) C.int { 29 | return C.MyBuffer_Size((*C.MyBuffer_T)(p)) 30 | } 31 | -------------------------------------------------------------------------------- /examples/ch2.8/class-cc2go/my_buffer_capi.h: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | typedef struct MyBuffer_T MyBuffer_T; 5 | 6 | MyBuffer_T* NewMyBuffer(int size); 7 | void DeleteMyBuffer(MyBuffer_T* p); 8 | 9 | char* MyBuffer_Data(MyBuffer_T* p); 10 | int MyBuffer_Size(MyBuffer_T* p); 11 | -------------------------------------------------------------------------------- /examples/ch2.8/class-go2cc/goobj.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | package main 5 | 6 | import ( 7 | "sync" 8 | ) 9 | 10 | type ObjectId int32 11 | 12 | var refs struct { 13 | sync.Mutex 14 | objs map[ObjectId]interface{} 15 | next ObjectId 16 | } 17 | 18 | func init() { 19 | refs.Lock() 20 | defer refs.Unlock() 21 | 22 | refs.objs = make(map[ObjectId]interface{}) 23 | refs.next = 1000 24 | } 25 | 26 | func NewObjectId(obj interface{}) ObjectId { 27 | refs.Lock() 28 | defer refs.Unlock() 29 | 30 | id := refs.next 31 | refs.next++ 32 | 33 | refs.objs[id] = obj 34 | return id 35 | } 36 | 37 | func (id ObjectId) IsNil() bool { 38 | return id == 0 39 | } 40 | 41 | func (id ObjectId) Get() interface{} { 42 | refs.Lock() 43 | defer refs.Unlock() 44 | 45 | return refs.objs[id] 46 | } 47 | 48 | func (id ObjectId) Free() interface{} { 49 | refs.Lock() 50 | defer refs.Unlock() 51 | 52 | obj := refs.objs[id] 53 | delete(refs.objs, id) 54 | 55 | return obj 56 | } 57 | -------------------------------------------------------------------------------- /examples/ch2.8/class-go2cc/main.cc: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | #include "person.h" 5 | 6 | #include 7 | 8 | extern "C" void Main() { 9 | auto p = Person::New("gopher", 10); 10 | 11 | char buf[64]; 12 | char* name = p->GetName(buf, sizeof(buf)-1); 13 | int age = p->GetAge(); 14 | 15 | printf("%s, %d years old.\n", name, age); 16 | p->Delete(); 17 | } 18 | -------------------------------------------------------------------------------- /examples/ch2.8/class-go2cc/main.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | package main 5 | 6 | // #cgo CXXFLAGS: -std=c++11 7 | // extern void Main(); 8 | import "C" 9 | 10 | func main() { 11 | C.Main() 12 | } 13 | -------------------------------------------------------------------------------- /examples/ch2.8/class-go2cc/persion.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | package main 5 | 6 | type Person struct { 7 | name string 8 | age int 9 | } 10 | 11 | func NewPerson(name string, age int) *Person { 12 | return &Person{ 13 | name: name, 14 | age: age, 15 | } 16 | } 17 | 18 | func (p *Person) Set(name string, age int) { 19 | p.name = name 20 | p.age = age 21 | } 22 | 23 | func (p *Person) Get() (name string, age int) { 24 | return p.name, p.age 25 | } 26 | -------------------------------------------------------------------------------- /examples/ch2.8/class-go2cc/person.cc: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | #include "person.h" 5 | -------------------------------------------------------------------------------- /examples/ch2.8/class-go2cc/person.h: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | extern "C" { 5 | #include "./person_capi.h" 6 | } 7 | 8 | struct Person { 9 | static Person* New(const char* name, int age) { 10 | return (Person*)person_new((char*)name, age); 11 | } 12 | void Delete() { 13 | person_delete(person_handle_t(this)); 14 | } 15 | 16 | void Set(char* name, int age) { 17 | person_set(person_handle_t(this), name, age); 18 | } 19 | char* GetName(char* buf, int size) { 20 | return person_get_name(person_handle_t(this), buf, size); 21 | } 22 | int GetAge() { 23 | return person_get_age(person_handle_t(this)); 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /examples/ch2.8/class-go2cc/person_capi.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | package main 5 | 6 | //#include "./person_capi.h" 7 | import "C" 8 | import "unsafe" 9 | 10 | //export person_new 11 | func person_new(name *C.char, age C.int) C.person_handle_t { 12 | id := NewObjectId(NewPerson(C.GoString(name), int(age))) 13 | return C.person_handle_t(id) 14 | } 15 | 16 | //export person_delete 17 | func person_delete(h C.person_handle_t) { 18 | ObjectId(h).Free() 19 | } 20 | 21 | //export person_set 22 | func person_set(h C.person_handle_t, name *C.char, age C.int) { 23 | p := ObjectId(h).Get().(*Person) 24 | p.Set(C.GoString(name), int(age)) 25 | } 26 | 27 | //export person_get_name 28 | func person_get_name(h C.person_handle_t, buf *C.char, size C.int) *C.char { 29 | p := ObjectId(h).Get().(*Person) 30 | name, _ := p.Get() 31 | 32 | n := int(size) - 1 33 | bufSlice := ((*[1 << 31]byte)(unsafe.Pointer(buf)))[0:n:n] 34 | n = copy(bufSlice, []byte(name)) 35 | bufSlice[n] = 0 36 | 37 | return buf 38 | } 39 | 40 | //export person_get_age 41 | func person_get_age(h C.person_handle_t) C.int { 42 | p := ObjectId(h).Get().(*Person) 43 | _, age := p.Get() 44 | return C.int(age) 45 | } 46 | -------------------------------------------------------------------------------- /examples/ch2.8/class-go2cc/person_capi.h: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | #include 5 | 6 | typedef uintptr_t person_handle_t; 7 | 8 | person_handle_t person_new(char* name, int age); 9 | void person_delete(person_handle_t p); 10 | 11 | void person_set(person_handle_t p, char* name, int age); 12 | char* person_get_name(person_handle_t p, char* buf, int size); 13 | int person_get_age(person_handle_t p); 14 | -------------------------------------------------------------------------------- /examples/ch2.9/incorrect-dll-api/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright © 2017 ChaiShushan . 2 | # License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | default: 5 | cd mystring && make 6 | go build -o a.out 7 | LD_LIBRARY_PATH=$(shell pwd)/mystring ./a.out 8 | 9 | macos: 10 | cd mystring && make 11 | go build -o a.out 12 | DYLD_LIBRARY_PATH=$(shell pwd)/mystring ./a.out 13 | 14 | windows: 15 | # set path 16 | 17 | clean: 18 | -cd mystring && make clean 19 | -rm *.a 20 | -rm a.out 21 | -------------------------------------------------------------------------------- /examples/ch2.9/incorrect-dll-api/main.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | package main 5 | 6 | //#cgo CFLAGS: -I./mystring 7 | //#cgo LDFLAGS: -L${SRCDIR}/mystring -lmystring 8 | // 9 | //#include "mystring.h" 10 | //#include 11 | import "C" 12 | import ( 13 | "fmt" 14 | "unsafe" 15 | ) 16 | 17 | func main() { 18 | cs := C.make_string(C.CString("hello")) 19 | defer C.free(unsafe.Pointer(cs)) 20 | 21 | fmt.Println(C.GoString(cs)) 22 | } 23 | -------------------------------------------------------------------------------- /examples/ch2.9/incorrect-dll-api/mystring/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright © 2017 ChaiShushan . 2 | # License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | default: 5 | gcc -shared -o libmystring.so mystring.c 6 | 7 | clean: 8 | -rm *.so 9 | -------------------------------------------------------------------------------- /examples/ch2.9/incorrect-dll-api/mystring/mystring.c: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | #include "mystring.h" 5 | 6 | #include 7 | 8 | static char buffer[1024]; 9 | 10 | static char* malloc(int size) { 11 | return &buffer[0]; 12 | } 13 | 14 | static void free(void* p) { 15 | // 16 | } 17 | 18 | char* make_string(const char* s) { 19 | char* p = malloc(strlen(s)+1); 20 | strcpy(p, s); 21 | return p; 22 | } 23 | 24 | void free_string(char* s) { 25 | free(s); 26 | } 27 | -------------------------------------------------------------------------------- /examples/ch2.9/incorrect-dll-api/mystring/mystring.h: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | char* make_string(const char* s); 5 | 6 | void free_string(char* s); 7 | -------------------------------------------------------------------------------- /examples/ch2.9/make-clib-dll/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright © 2017 ChaiShushan . 2 | # License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | default: 5 | go build -buildmode=c-archive -o number.a 6 | gcc -o a.out _test_main.c number.a 7 | ./a.out 8 | 9 | build_on_win64: 10 | go build -buildmode=c-archive -o number.a 11 | gcc -m64 -shared -o number-win64.dll number-win64.def number.a -Wl,--allow-multiple-definition -static -lstdc++ -lwinmm -lntdll -lWs2_32 12 | lib /def:number-win64.def /machine:x64 13 | 14 | build_with_vc: 15 | cl -o a.out.exe _test_main.c number-win64.lib 16 | 17 | clean: 18 | -rm *.a *.lib 19 | -rm a.out 20 | -rm a.out.exe 21 | -------------------------------------------------------------------------------- /examples/ch2.9/make-clib-dll/_test_main.c: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | #include "number.h" 5 | 6 | #include 7 | 8 | int main() { 9 | int a = 10; 10 | int b = 5; 11 | int c = 12; 12 | 13 | int x = number_add_mod(a, b, c); 14 | printf("(%d+%d)%%%d = %d\n", a, b, c, x); 15 | 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /examples/ch2.9/make-clib-dll/main.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | package main 5 | 6 | import "C" 7 | 8 | func main() {} 9 | 10 | //export number_add_mod 11 | func number_add_mod(a, b, mod C.int) C.int { 12 | return (a + b) % mod 13 | } 14 | -------------------------------------------------------------------------------- /examples/ch2.9/make-clib-dll/number-win64.def: -------------------------------------------------------------------------------- 1 | LIBRARY number-win64.dll 2 | 3 | EXPORTS 4 | number_add_mod 5 | -------------------------------------------------------------------------------- /examples/ch2.9/make-clib-from-multi-pkg/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright © 2017 ChaiShushan . 2 | # License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | default: 5 | go build -buildmode=c-archive -o main.a 6 | gcc -o a.out _test_main.c main.a 7 | ./a.out 8 | 9 | clean: 10 | -rm *.a *.lib 11 | -rm a.out 12 | -rm a.out.exe 13 | -------------------------------------------------------------------------------- /examples/ch2.9/make-clib-from-multi-pkg/_test_main.c: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | #include "main.h" 5 | #include "./number/number.h" 6 | 7 | #include 8 | 9 | int main() { 10 | int a = 10; 11 | int b = 5; 12 | int c = 12; 13 | 14 | int x = number_add_mod(a, b, c); 15 | printf("(%d+%d)%%%d = %d\n", a, b, c, x); 16 | 17 | goPrintln("done"); 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /examples/ch2.9/make-clib-from-multi-pkg/main.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | package main 5 | 6 | import "C" 7 | 8 | import ( 9 | "fmt" 10 | 11 | _"gobook.examples/ch2-09-so-and-lib/make-clib-from-multi-pkg/number" 12 | ) 13 | 14 | func main() { 15 | println("Done") 16 | } 17 | 18 | //export goPrintln 19 | func goPrintln(s *C.char) { 20 | fmt.Println("goPrintln:", C.GoString(s)) 21 | } 22 | -------------------------------------------------------------------------------- /examples/ch2.9/make-clib-from-multi-pkg/number/number.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | package number 5 | 6 | import "C" 7 | 8 | //export number_add_mod 9 | func number_add_mod(a, b, mod C.int) C.int { 10 | return (a + b) % mod 11 | } 12 | -------------------------------------------------------------------------------- /examples/ch2.9/make-clib-from-multi-pkg/number/number.h: -------------------------------------------------------------------------------- 1 | int number_add_mod(int a, int b, int mod); 2 | -------------------------------------------------------------------------------- /examples/ch2.9/make-clib-shared/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright © 2017 ChaiShushan . 2 | # License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | default: 5 | go build -buildmode=c-shared -o number.so 6 | gcc -o a.out _test_main.c number.so 7 | ./a.out 8 | 9 | clean: 10 | -rm *.a 11 | -rm a.out 12 | -------------------------------------------------------------------------------- /examples/ch2.9/make-clib-shared/_test_main.c: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | #include "number.h" 5 | 6 | #include 7 | 8 | int main() { 9 | int a = 10; 10 | int b = 5; 11 | int c = 12; 12 | 13 | int x = number_add_mod(a, b, c); 14 | printf("(%d+%d)%%%d = %d\n", a, b, c, x); 15 | 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /examples/ch2.9/make-clib-shared/main.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | package main 5 | 6 | import "C" 7 | 8 | func main() {} 9 | 10 | //export number_add_mod 11 | func number_add_mod(a, b, mod C.int) C.int { 12 | return (a + b) % mod 13 | } 14 | -------------------------------------------------------------------------------- /examples/ch2.9/make-clib-static/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright © 2017 ChaiShushan . 2 | # License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | default: 5 | go build -buildmode=c-archive -o number.a 6 | gcc -o a.out _test_main.c number.a 7 | ./a.out 8 | 9 | clean: 10 | -rm *.a 11 | -rm a.out 12 | -------------------------------------------------------------------------------- /examples/ch2.9/make-clib-static/_test_main.c: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | #include "number.h" 5 | 6 | #include 7 | 8 | int main() { 9 | int a = 10; 10 | int b = 5; 11 | int c = 12; 12 | 13 | int x = number_add_mod(a, b, c); 14 | printf("(%d+%d)%%%d = %d\n", a, b, c, x); 15 | 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /examples/ch2.9/make-clib-static/main.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | package main 5 | 6 | import "C" 7 | 8 | func main() {} 9 | 10 | //export number_add_mod 11 | func number_add_mod(a, b, mod C.int) C.int { 12 | return (a + b) % mod 13 | } 14 | -------------------------------------------------------------------------------- /examples/ch2.9/plugin/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright © 2017 ChaiShushan . 2 | # License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | default: 5 | go build -buildmode=plugin plugin.go -o plugin.so 6 | 7 | clean: 8 | -rm *.so 9 | -------------------------------------------------------------------------------- /examples/ch2.9/plugin/main.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | package main 5 | 6 | import "plugin" 7 | 8 | func main() { 9 | p, err := plugin.Open("plugin.so") 10 | if err != nil { 11 | panic(err) 12 | } 13 | v, err := p.Lookup("V") 14 | if err != nil { 15 | panic(err) 16 | } 17 | f, err := p.Lookup("F") 18 | if err != nil { 19 | panic(err) 20 | } 21 | *v.(*int) = 7 22 | f.(func())() // prints "Hello, number 7" 23 | } 24 | -------------------------------------------------------------------------------- /examples/ch2.9/plugin/plugin.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // +build ignore 5 | // +build go1.10 6 | 7 | package main 8 | 9 | import "fmt" 10 | 11 | func main() 12 | 13 | var V int 14 | 15 | func F() { fmt.Printf("Hello, number %d\n", V) } 16 | -------------------------------------------------------------------------------- /examples/ch2.9/use-clib-shared/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright © 2017 ChaiShushan . 2 | # License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | default: 5 | cd number && make 6 | go build -o a.out 7 | LD_LIBRARY_PATH=$(shell pwd)/number ./a.out 8 | 9 | macos: 10 | cd number && make 11 | go build -o a.out 12 | DYLD_LIBRARY_PATH=$(shell pwd)/number ./a.out 13 | 14 | windows: 15 | # set path 16 | 17 | clean: 18 | -cd number && make clean 19 | -rm *.a 20 | -rm a.out 21 | -------------------------------------------------------------------------------- /examples/ch2.9/use-clib-shared/main.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | package main 5 | 6 | //#cgo CFLAGS: -I./number 7 | //#cgo LDFLAGS: -L${SRCDIR}/number -lnumber 8 | // 9 | //#include "number.h" 10 | import "C" 11 | import "fmt" 12 | 13 | func main() { 14 | fmt.Println(C.number_add_mod(10, 5, 12)) 15 | } 16 | -------------------------------------------------------------------------------- /examples/ch2.9/use-clib-shared/number/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright © 2017 ChaiShushan . 2 | # License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | default: 5 | gcc -shared -o libnumber.so number.c 6 | 7 | clean: 8 | -rm *.so 9 | -------------------------------------------------------------------------------- /examples/ch2.9/use-clib-shared/number/number.c: -------------------------------------------------------------------------------- 1 | #include "number.h" 2 | 3 | int number_add_mod(int a, int b, int mod) { 4 | return (a+b)%mod; 5 | } 6 | -------------------------------------------------------------------------------- /examples/ch2.9/use-clib-shared/number/number.h: -------------------------------------------------------------------------------- 1 | int number_add_mod(int a, int b, int mod); 2 | -------------------------------------------------------------------------------- /examples/ch2.9/use-clib-static-v1/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright © 2017 ChaiShushan . 2 | # License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | default: 5 | cd number && make 6 | go run main.go 7 | 8 | clean: 9 | -cd number && make clean 10 | -rm *.a 11 | -rm a.out 12 | -------------------------------------------------------------------------------- /examples/ch2.9/use-clib-static-v1/main.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | package main 5 | 6 | //#cgo CFLAGS: -I./number 7 | //#cgo LDFLAGS: -L${SRCDIR}/number -lnumber 8 | // 9 | //#include "number.h" 10 | import "C" 11 | import "fmt" 12 | 13 | func main() { 14 | fmt.Println(C.number_add_mod(10, 5, 12)) 15 | } 16 | -------------------------------------------------------------------------------- /examples/ch2.9/use-clib-static-v1/number/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright © 2017 ChaiShushan . 2 | # License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | default: 5 | gcc -c -o number.o number.c 6 | ar rcs libnumber.a number.o 7 | -rm *.o 8 | 9 | clean: 10 | -rm *.a *.o 11 | -------------------------------------------------------------------------------- /examples/ch2.9/use-clib-static-v1/number/number.c: -------------------------------------------------------------------------------- 1 | #include "number.h" 2 | 3 | int number_add_mod(int a, int b, int mod) { 4 | return (a+b)%mod; 5 | } 6 | -------------------------------------------------------------------------------- /examples/ch2.9/use-clib-static-v1/number/number.h: -------------------------------------------------------------------------------- 1 | int number_add_mod(int a, int b, int mod); 2 | -------------------------------------------------------------------------------- /examples/ch2.9/use-clib-static-v2/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright © 2017 ChaiShushan . 2 | # License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | default: 5 | go build -o a.out 6 | ./a.out 7 | 8 | clean: 9 | -rm a.out 10 | -------------------------------------------------------------------------------- /examples/ch2.9/use-clib-static-v2/main.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | package main 5 | 6 | //#cgo CFLAGS: -I./number 7 | //#include "number.h" 8 | import "C" 9 | import "fmt" 10 | 11 | func main() { 12 | fmt.Println(C.number_add_mod(10, 5, 12)) 13 | } 14 | -------------------------------------------------------------------------------- /examples/ch2.9/use-clib-static-v2/number/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright © 2017 ChaiShushan . 2 | # License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | default: 5 | gcc -c -o number.o number.c 6 | ar rcs libnumber.a number.o 7 | -rm *.o 8 | 9 | clean: 10 | -rm *.a *.o 11 | -------------------------------------------------------------------------------- /examples/ch2.9/use-clib-static-v2/number/number.c: -------------------------------------------------------------------------------- 1 | #include "number.h" 2 | 3 | int number_add_mod(int a, int b, int mod) { 4 | return (a+b)%mod; 5 | } 6 | -------------------------------------------------------------------------------- /examples/ch2.9/use-clib-static-v2/number/number.h: -------------------------------------------------------------------------------- 1 | int number_add_mod(int a, int b, int mod); 2 | -------------------------------------------------------------------------------- /examples/ch2.9/use-clib-static-v2/z_link_number_c.c: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | #include "./number/number.c" 5 | -------------------------------------------------------------------------------- /examples/ch2.x/hello-swig-v1/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright © 2017 ChaiShushan . 2 | # License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | default: 5 | go run runme.go 6 | 7 | clean: 8 | -rm a.out 9 | -------------------------------------------------------------------------------- /examples/ch2.x/hello-swig-v1/hello.cc: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 ChaiShushan (chaishushan{AT}gmail.com). 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | #include 5 | 6 | void SayHello() { 7 | std::cout << "Hello, World!" << std::endl; 8 | } 9 | -------------------------------------------------------------------------------- /examples/ch2.x/hello-swig-v1/hello.swigcxx: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 ChaiShushan (chaishushan{AT}gmail.com). 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | %module hello 5 | 6 | %inline %{ 7 | extern void SayHello(); 8 | %} 9 | -------------------------------------------------------------------------------- /examples/ch2.x/hello-swig-v1/hello_test.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 ChaiShushan (chaishushan{AT}gmail.com). 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | package hello 5 | 6 | import ( 7 | "testing" 8 | ) 9 | 10 | func TestSayHello(t *testing.T) { 11 | SayHello() 12 | } 13 | -------------------------------------------------------------------------------- /examples/ch2.x/hello-swig-v1/runme.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 ChaiShushan (chaishushan{AT}gmail.com). 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // +build ignore 5 | 6 | package main 7 | 8 | import ( 9 | hello "." 10 | ) 11 | 12 | func main() { 13 | hello.SayHello() 14 | } 15 | -------------------------------------------------------------------------------- /examples/ch2.x/hello-swig-v2/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright © 2017 ChaiShushan . 2 | # License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | # use go generate 5 | 6 | default: 7 | swig -go -cgo -intgosize 64 -o swig_wrap.cc hello.i 8 | go run runme.go 9 | 10 | clean: 11 | -rm a.out 12 | -------------------------------------------------------------------------------- /examples/ch2.x/hello-swig-v2/hello.cc: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 ChaiShushan (chaishushan{AT}gmail.com). 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | #include 5 | 6 | void SayHello() { 7 | std::cout << "Hello, World!" << std::endl; 8 | } 9 | -------------------------------------------------------------------------------- /examples/ch2.x/hello-swig-v2/hello.i: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 ChaiShushan (chaishushan{AT}gmail.com). 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | %module hello 5 | 6 | %inline %{ 7 | extern void SayHello(); 8 | %} 9 | 10 | -------------------------------------------------------------------------------- /examples/ch2.x/hello-swig-v2/runme.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 ChaiShushan (chaishushan{AT}gmail.com). 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // +build ignore 5 | 6 | package main 7 | 8 | import ( 9 | hello "." 10 | ) 11 | 12 | func main() { 13 | hello.SayHello() 14 | } 15 | -------------------------------------------------------------------------------- /examples/ch2.x/hello/.gitignore: -------------------------------------------------------------------------------- 1 | !/_obj 2 | -------------------------------------------------------------------------------- /examples/ch2.x/hello/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright © 2017 ChaiShushan . 2 | # License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | default: 5 | go tool cgo hello.go 6 | -------------------------------------------------------------------------------- /examples/ch2.x/hello/_obj/_cgo_flags: -------------------------------------------------------------------------------- 1 | _CGO_CFLAGS= 2 | -------------------------------------------------------------------------------- /examples/ch2.x/hello/_obj/_cgo_main.c: -------------------------------------------------------------------------------- 1 | int main() { return 0; } 2 | void crosscall2(void(*fn)(void*, int, __SIZE_TYPE__), void *a, int c, __SIZE_TYPE__ ctxt) { } 3 | __SIZE_TYPE__ _cgo_wait_runtime_init_done() { return 0; } 4 | void _cgo_release_context(__SIZE_TYPE__ ctxt) { } 5 | char* _cgo_topofstack(void) { return (char*)0; } 6 | void _cgo_allocate(void *a, int c) { } 7 | void _cgo_panic(void *a, int c) { } 8 | void _cgo_reginit(void) { } 9 | #line 1 "cgo-generated-wrappers" 10 | int _cgoexp_16f1900c27a8_helloInt; 11 | int _cgoexp_16f1900c27a8_helloString; 12 | int _cgoexp_16f1900c27a8_helloSlice; 13 | -------------------------------------------------------------------------------- /examples/ch2.x/hello/_obj/hello.cgo1.go: -------------------------------------------------------------------------------- 1 | // Created by cgo - DO NOT EDIT 2 | 3 | //line /Users/chai/go/src/github.com/chai2010/advanced-go-programming-book/examples/ch2-xx/hello/hello.go:1 4 | package main 5 | 6 | //line /Users/chai/go/src/github.com/chai2010/advanced-go-programming-book/examples/ch2-xx/hello/hello.go:5 7 | func main() { 8 | helloString("hello") 9 | } 10 | 11 | //line /Users/chai/go/src/github.com/chai2010/advanced-go-programming-book/examples/ch2-xx/hello/hello.go:10 12 | func helloInt(s int) { 13 | println(s) 14 | } 15 | 16 | //line /Users/chai/go/src/github.com/chai2010/advanced-go-programming-book/examples/ch2-xx/hello/hello.go:15 17 | func helloString(s string) { 18 | println(s) 19 | } 20 | 21 | //line /Users/chai/go/src/github.com/chai2010/advanced-go-programming-book/examples/ch2-xx/hello/hello.go:20 22 | func helloSlice(s []byte) { 23 | println(string(s)) 24 | } 25 | -------------------------------------------------------------------------------- /examples/ch2.x/hello/_obj/hello.cgo2.c: -------------------------------------------------------------------------------- 1 | 2 | 3 | #line 1 "cgo-gcc-prolog" 4 | /* 5 | If x and y are not equal, the type will be invalid 6 | (have a negative array count) and an inscrutable error will come 7 | out of the compiler and hopefully mention "name". 8 | */ 9 | #define __cgo_compile_assert_eq(x, y, name) typedef char name[(x-y)*(x-y)*-2+1]; 10 | 11 | /* Check at compile time that the sizes we use match our expectations. */ 12 | #define __cgo_size_assert(t, n) __cgo_compile_assert_eq(sizeof(t), n, _cgo_sizeof_##t##_is_not_##n) 13 | 14 | __cgo_size_assert(char, 1) 15 | __cgo_size_assert(short, 2) 16 | __cgo_size_assert(int, 4) 17 | typedef long long __cgo_long_long; 18 | __cgo_size_assert(__cgo_long_long, 8) 19 | __cgo_size_assert(float, 4) 20 | __cgo_size_assert(double, 8) 21 | 22 | extern char* _cgo_topofstack(void); 23 | 24 | #include 25 | #include 26 | 27 | 28 | #define CGO_NO_SANITIZE_THREAD 29 | #define _cgo_tsan_acquire() 30 | #define _cgo_tsan_release() 31 | 32 | -------------------------------------------------------------------------------- /examples/ch2.x/hello/hello.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | package main 5 | 6 | import "C" 7 | 8 | func main() { 9 | helloString("hello") // _GoString_ 10 | } 11 | 12 | //export helloInt 13 | func helloInt(s int) { 14 | println(s) 15 | } 16 | 17 | //export helloString 18 | func helloString(s string) { 19 | println(s) 20 | } 21 | 22 | //export helloSlice 23 | func helloSlice(s []byte) { 24 | println(string(s)) 25 | } 26 | -------------------------------------------------------------------------------- /examples/ch3.1/id-01/pkg.go: -------------------------------------------------------------------------------- 1 | package pkg 2 | 3 | var Id = 9527 4 | -------------------------------------------------------------------------------- /examples/ch3.1/id-01/runme.go: -------------------------------------------------------------------------------- 1 | // +build ignore 2 | 3 | package main 4 | 5 | import pkg "." 6 | 7 | func main() { 8 | println(pkg.Id) 9 | } 10 | -------------------------------------------------------------------------------- /examples/ch3.1/id-02/pkg.go: -------------------------------------------------------------------------------- 1 | package pkg 2 | 3 | var Id int 4 | -------------------------------------------------------------------------------- /examples/ch3.1/id-02/pkg_amd64.s: -------------------------------------------------------------------------------- 1 | 2 | DATA ·Id+0(SB)/1,$0x37 3 | DATA ·Id+1(SB)/1,$0x25 4 | DATA ·Id+2(SB)/1,$0x00 5 | DATA ·Id+3(SB)/1,$0x00 6 | DATA ·Id+4(SB)/1,$0x00 7 | DATA ·Id+5(SB)/1,$0x00 8 | DATA ·Id+6(SB)/1,$0x00 9 | DATA ·Id+7(SB)/1,$0x00 10 | 11 | GLOBL ·Id(SB),$8 12 | -------------------------------------------------------------------------------- /examples/ch3.1/id-02/runme.go: -------------------------------------------------------------------------------- 1 | // +build ignore 2 | 3 | package main 4 | 5 | import ( 6 | pkg "." 7 | ) 8 | 9 | func main() { 10 | println(pkg.Id) 11 | } 12 | -------------------------------------------------------------------------------- /examples/ch3.1/main-01/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright 2018 . All rights reserved. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | default: 6 | -go build -o a.out && ./a.out 7 | -@rm a.out 8 | 9 | clean: 10 | -@rm a.out 11 | -------------------------------------------------------------------------------- /examples/ch3.1/main-01/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | var helloworld = "你好, 世界" 4 | 5 | func main() 6 | -------------------------------------------------------------------------------- /examples/ch3.1/main-01/main_amd64.s: -------------------------------------------------------------------------------- 1 | 2 | TEXT ·main(SB), $16-0 3 | MOVQ ·helloworld+0(SB), AX; MOVQ AX, 0(SP) 4 | MOVQ ·helloworld+8(SB), BX; MOVQ BX, 8(SP) 5 | CALL runtime·printstring(SB) 6 | CALL runtime·printnl(SB) 7 | RET 8 | -------------------------------------------------------------------------------- /examples/ch3.1/str-01/pkg.go: -------------------------------------------------------------------------------- 1 | package pkg 2 | 3 | var Name = "gopher" 4 | -------------------------------------------------------------------------------- /examples/ch3.1/str-02/pkg.go: -------------------------------------------------------------------------------- 1 | package pkg 2 | 3 | var NameData [8]byte 4 | 5 | var Name string 6 | -------------------------------------------------------------------------------- /examples/ch3.1/str-02/pkg_amd64.s: -------------------------------------------------------------------------------- 1 | 2 | 3 | GLOBL ·NameData(SB),$8 4 | DATA ·NameData(SB)/8,$"gopher" 5 | 6 | GLOBL ·Name(SB),$16 7 | DATA ·Name+0(SB)/8,$·NameData(SB) 8 | DATA ·Name+8(SB)/8,$6 9 | -------------------------------------------------------------------------------- /examples/ch3.1/str-02/runme.go: -------------------------------------------------------------------------------- 1 | // +build ignore 2 | 3 | package main 4 | 5 | import ( 6 | pkg "." 7 | ) 8 | 9 | func main() { 10 | println(pkg.Name) 11 | 12 | pkg.NameData[0] = '?' 13 | println(pkg.Name) 14 | } 15 | -------------------------------------------------------------------------------- /examples/ch3.1/str-03/pkg.go: -------------------------------------------------------------------------------- 1 | package pkg 2 | 3 | var NameData [8]byte 4 | 5 | var Name string 6 | -------------------------------------------------------------------------------- /examples/ch3.1/str-03/pkg_amd64.s: -------------------------------------------------------------------------------- 1 | GLOBL ·Name(SB),$24 2 | 3 | DATA ·Name+0(SB)/8,$·Name+16(SB) 4 | DATA ·Name+8(SB)/8,$6 5 | DATA ·Name+16(SB)/8,$"gopher" 6 | -------------------------------------------------------------------------------- /examples/ch3.1/str-03/runme.go: -------------------------------------------------------------------------------- 1 | // +build ignore 2 | 3 | package main 4 | 5 | import ( 6 | pkg "." 7 | ) 8 | 9 | func main() { 10 | println(pkg.Name) 11 | } 12 | -------------------------------------------------------------------------------- /examples/ch3.6/asm-split/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | //go:nosplit 4 | func main() { 5 | printnl() 6 | } 7 | 8 | func printnl() 9 | -------------------------------------------------------------------------------- /examples/ch3.6/asm-split/main_amd64.s: -------------------------------------------------------------------------------- 1 | 2 | #define NOSPLIT 4 3 | 4 | TEXT ·printnl_nosplit(SB), NOSPLIT, $8 5 | CALL runtime·printnl(SB) 6 | RET 7 | 8 | TEXT ·printnl(SB), $8 9 | CALL runtime·printnl(SB) 10 | RET 11 | -------------------------------------------------------------------------------- /examples/ch3.6/closure-01/main.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2018 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | package main 5 | 6 | func NewTwiceFunClosure(x int) func() int { 7 | return func() int { 8 | x *= 2 9 | return x 10 | } 11 | } 12 | 13 | func main() { 14 | fnTwice := NewTwiceFunClosure(1) 15 | 16 | println(fnTwice()) // 1*2 => 2 17 | println(fnTwice()) // 2*2 => 4 18 | println(fnTwice()) // 4*2 => 8 19 | } 20 | -------------------------------------------------------------------------------- /examples/ch3.6/closure-02/main.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2018 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | package main 5 | 6 | import ( 7 | "unsafe" 8 | ) 9 | 10 | type FunTwiceClosure struct { 11 | F uintptr 12 | X int 13 | } 14 | 15 | func NewTwiceFunClosure(x int) func() int { 16 | var p = &FunTwiceClosure{ 17 | F: asmFunTwiceClosureAddr(), 18 | X: x, 19 | } 20 | return ptrToFunc(unsafe.Pointer(p)) 21 | } 22 | 23 | func ptrToFunc(p unsafe.Pointer) func() int 24 | 25 | func asmFunTwiceClosureAddr() uintptr 26 | func asmFunTwiceClosureBody() int 27 | 28 | func main() { 29 | fnTwice := NewTwiceFunClosure(1) 30 | 31 | println(fnTwice()) // 1*2 => 2 32 | println(fnTwice()) // 2*2 => 4 33 | println(fnTwice()) // 4*2 => 8 34 | } 35 | -------------------------------------------------------------------------------- /examples/ch3.6/closure-02/main_amd64.s: -------------------------------------------------------------------------------- 1 | // Copyright © 2018 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | #include "textflag.h" 5 | 6 | TEXT ·ptrToFunc(SB), NOSPLIT, $0-16 7 | MOVQ ptr+0(FP), AX // AX = ptr 8 | MOVQ AX, ret+8(FP) // return AX 9 | RET 10 | 11 | TEXT ·asmFunTwiceClosureAddr(SB), NOSPLIT, $0-8 12 | LEAQ ·asmFunTwiceClosureBody(SB), AX // AX = ·asmFunTwiceClosureBody(SB) 13 | MOVQ AX, ret+0(FP) // return AX 14 | RET 15 | 16 | TEXT ·asmFunTwiceClosureBody(SB), NOSPLIT|NEEDCTXT, $0-8 17 | MOVQ 8(DX), AX 18 | ADDQ AX , AX // AX *= 2 19 | MOVQ AX , 8(DX) // ctx.X = AX 20 | MOVQ AX , ret+0(FP) // return AX 21 | RET 22 | 23 | -------------------------------------------------------------------------------- /examples/ch3.8/ch3.8-1/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | func main() { 4 | panic("goid") 5 | } 6 | -------------------------------------------------------------------------------- /examples/ch3.8/ch3.8-2/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "runtime" 4 | 5 | func main() { 6 | var buf = make([]byte, 64) 7 | var stk = buf[:runtime.Stack(buf, false)] 8 | println(string(stk)) 9 | } 10 | -------------------------------------------------------------------------------- /examples/ch3.8/ch3.8-3/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "runtime" 6 | "strconv" 7 | "strings" 8 | "time" 9 | ) 10 | 11 | func main() { 12 | println("a:", GetGoid()) 13 | go func() { 14 | println("b:", GetGoid()) 15 | }() 16 | 17 | time.Sleep(time.Second) 18 | } 19 | 20 | func GetGoid() int64 { 21 | var ( 22 | buf [64]byte 23 | n = runtime.Stack(buf[:], false) 24 | stk = strings.TrimPrefix(string(buf[:n]), "goroutine ") 25 | ) 26 | 27 | idField := strings.Fields(stk)[0] 28 | id, err := strconv.Atoi(idField) 29 | if err != nil { 30 | panic(fmt.Errorf("can not get goroutine id: %v", err)) 31 | } 32 | 33 | return int64(id) 34 | } 35 | -------------------------------------------------------------------------------- /examples/ch3.8/ch3.8-4/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "unsafe" 5 | ) 6 | 7 | func getg() unsafe.Pointer 8 | 9 | const g_goid_offset = 152 // Go1.8/Go1.9/Go1.10/Go1.11/Go1.12/Go1.13 10 | 11 | func GetGroutineId() int64 { 12 | g := getg() 13 | p := (*int64)(unsafe.Pointer(uintptr(g) + g_goid_offset)) 14 | return *p 15 | } 16 | 17 | func main() { 18 | println(GetGroutineId()) 19 | } 20 | -------------------------------------------------------------------------------- /examples/ch3.8/ch3.8-4/main_amd64.s: -------------------------------------------------------------------------------- 1 | #include "textflag.h" 2 | 3 | // func getg() unsafe.Pointer 4 | TEXT ·getg(SB), NOSPLIT, $0-8 5 | MOVQ (TLS), AX 6 | MOVQ AX, ret+0(FP) 7 | RET 8 | -------------------------------------------------------------------------------- /examples/ch3.8/ch3.8-5/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "reflect" 5 | "time" 6 | ) 7 | 8 | func getg() interface{} 9 | 10 | type eface struct { 11 | _type, elem uintptr 12 | } 13 | 14 | //go:nosplit 15 | func runtime_convT2E_hack(_type, elem uintptr) eface { 16 | return eface{ 17 | _type: _type, 18 | elem: elem, 19 | } 20 | } 21 | 22 | func GetGoid() int64 { 23 | g := getg() 24 | goid := reflect.ValueOf(g).FieldByName("goid").Int() 25 | return goid 26 | } 27 | func main() { 28 | println("a:", GetGoid()) 29 | go func() { 30 | println("b:", GetGoid()) 31 | }() 32 | 33 | time.Sleep(time.Second) 34 | } 35 | -------------------------------------------------------------------------------- /examples/ch3.8/ch3.8-5/main_amd64.s: -------------------------------------------------------------------------------- 1 | #include "textflag.h" 2 | 3 | // func getg() interface{} 4 | TEXT ·getg(SB), NOSPLIT, $32-16 5 | // get runtime.g 6 | MOVQ (TLS), AX 7 | // get runtime.g type 8 | MOVQ $type·runtime·g(SB), BX 9 | 10 | // convert (*g) to interface{} 11 | MOVQ AX, 8(SP) 12 | MOVQ BX, 0(SP) 13 | CALL ·runtime_convT2E_hack(SB) 14 | MOVQ 16(SP), AX 15 | MOVQ 24(SP), BX 16 | 17 | // return interface{} 18 | MOVQ AX, ret+0(FP) 19 | MOVQ BX, ret+8(FP) 20 | RET 21 | -------------------------------------------------------------------------------- /examples/ch3.8/ch3.8-6/gls/gls.go: -------------------------------------------------------------------------------- 1 | package gls 2 | 3 | import "sync" 4 | 5 | var gls struct { 6 | m map[int64]map[interface{}]interface{} 7 | sync.Mutex 8 | } 9 | 10 | func init() { 11 | gls.m = make(map[int64]map[interface{}]interface{}) 12 | } 13 | 14 | func getMap() map[interface{}]interface{} { 15 | gls.Lock() 16 | defer gls.Unlock() 17 | 18 | goid := GetGoid() 19 | if m, _ := gls.m[goid]; m != nil { 20 | return m 21 | } 22 | 23 | m := make(map[interface{}]interface{}) 24 | gls.m[goid] = m 25 | return m 26 | } 27 | 28 | func Get(key interface{}) interface{} { 29 | return getMap()[key] 30 | } 31 | func Put(key interface{}, v interface{}) { 32 | getMap()[key] = v 33 | } 34 | func Delete(key interface{}) { 35 | delete(getMap(), key) 36 | } 37 | 38 | func Clean() { 39 | gls.Lock() 40 | defer gls.Unlock() 41 | 42 | delete(gls.m, GetGoid()) 43 | } 44 | -------------------------------------------------------------------------------- /examples/ch3.8/ch3.8-6/gls/goid.go: -------------------------------------------------------------------------------- 1 | package gls 2 | 3 | import ( 4 | "reflect" 5 | ) 6 | 7 | func getg() interface{} 8 | 9 | type eface struct { 10 | _type, elem uintptr 11 | } 12 | 13 | //go:nosplit 14 | func runtime_convT2E_hack(_type, elem uintptr) eface { 15 | return eface{ 16 | _type: _type, 17 | elem: elem, 18 | } 19 | } 20 | 21 | func GetGoid() int64 { 22 | g := getg() 23 | goid := reflect.ValueOf(g).FieldByName("goid").Int() 24 | return goid 25 | } 26 | -------------------------------------------------------------------------------- /examples/ch3.8/ch3.8-6/gls/goid_amd64.s: -------------------------------------------------------------------------------- 1 | #include "textflag.h" 2 | 3 | // func getg() interface{} 4 | TEXT ·getg(SB), NOSPLIT, $32-16 5 | // get runtime.g 6 | MOVQ (TLS), AX 7 | // get runtime.g type 8 | MOVQ $type·runtime·g(SB), BX 9 | 10 | // convert (*g) to interface{} 11 | MOVQ AX, 8(SP) 12 | MOVQ BX, 0(SP) 13 | CALL ·runtime_convT2E_hack(SB) 14 | MOVQ 16(SP), AX 15 | MOVQ 24(SP), BX 16 | 17 | // return interface{} 18 | MOVQ AX, ret+0(FP) 19 | MOVQ BX, ret+8(FP) 20 | RET 21 | -------------------------------------------------------------------------------- /examples/ch3.8/ch3.8-6/go.mod: -------------------------------------------------------------------------------- 1 | module gobook/ch3.8-6 2 | 3 | go 1.13 4 | -------------------------------------------------------------------------------- /examples/ch3.8/ch3.8-6/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "sync" 6 | 7 | "gobook/ch3.8-6/gls" 8 | ) 9 | 10 | func main() { 11 | var wg sync.WaitGroup 12 | for i := 0; i < 5; i++ { 13 | wg.Add(1) 14 | go func(idx int) { 15 | defer wg.Done() 16 | defer gls.Clean() 17 | 18 | defer func() { 19 | fmt.Printf("%d: number = %d\n", idx, gls.Get("number")) 20 | }() 21 | gls.Put("number", idx+100) 22 | }(i) 23 | } 24 | wg.Wait() 25 | } 26 | -------------------------------------------------------------------------------- /examples/ch3.8/hello-asm/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | func main() { asmSayHello() } 4 | 5 | func asmSayHello() 6 | -------------------------------------------------------------------------------- /examples/ch3.8/hello-asm/main_amd64.s: -------------------------------------------------------------------------------- 1 | #include "textflag.h" 2 | #include "funcdata.h" 3 | 4 | // "Hello World!\n" 5 | DATA text<>+0(SB)/8,$"Hello Wo" 6 | DATA text<>+8(SB)/8,$"rld!\n" 7 | GLOBL text<>(SB),NOPTR,$16 8 | 9 | // func asmSayHello() 10 | TEXT ·asmSayHello(SB), $16-0 11 | NO_LOCAL_POINTERS 12 | MOVQ $text<>+0(SB), AX 13 | MOVQ AX, (SP) 14 | MOVQ $16, 8(SP) 15 | CALL runtime·printstring(SB) 16 | RET 17 | -------------------------------------------------------------------------------- /examples/ch3.8/hello/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | func main() { 8 | nums := make([]int, 5) 9 | for i := 0; i < len(nums); i++ { 10 | nums[i] = i * i 11 | } 12 | fmt.Println(nums) 13 | } 14 | -------------------------------------------------------------------------------- /examples/ch3.x/add/add.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // Go版本, 支持内联优化 5 | 6 | package add 7 | 8 | func Add(a, b int) int { 9 | return a + b 10 | } 11 | 12 | func AddSlice(dst, a, b []int) { 13 | for i := 0; i < len(dst) && i < len(a) && i < len(b); i++ { 14 | dst[i] = a[i] + b[i] 15 | } 16 | return 17 | } 18 | -------------------------------------------------------------------------------- /examples/ch3.x/add/add_asm.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // +build amd64 5 | 6 | // 汇编版本, 不支持内联优化 7 | 8 | package add 9 | 10 | func AsmAdd(a, b int) int 11 | 12 | func AsmAddSlice(dst, a, b []int) { 13 | AddSlice(dst, a, b) 14 | } 15 | 16 | func AsmAddSlice__todo(dst, a, b []int) 17 | -------------------------------------------------------------------------------- /examples/ch3.x/add/add_asm_amd64.s: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | #include "textflag.h" 5 | 6 | // func AsmAdd(a, b int) int 7 | TEXT ·AsmAdd(SB), NOSPLIT, $0-24 8 | MOVQ a+0(FP), AX // a 9 | MOVQ b+8(FP), BX // b 10 | ADDQ AX, BX // a+b 11 | MOVQ BX, ret+16(FP) // return a+b 12 | RET 13 | 14 | // func AsmAddSlice(dst, a, b []int) 15 | TEXT ·AsmAddSlice__todo(SB), NOSPLIT, $0-72 16 | MOVQ dst+0(FP), AX // AX: dst 17 | MOVQ a+24(FP), BX // BX: &a 18 | MOVQ b+48(FP), CX // CX: &b 19 | MOVQ dst_len+8(FP), DX // DX: len(dst) 20 | MOVQ a_len+32(FP), R8 // R8: len(a) 21 | MOVQ b_len+56(FP), R9 // R9: len(b) 22 | // TODO: DX = min(DX,R8,R9) 23 | RET 24 | -------------------------------------------------------------------------------- /examples/ch3.x/add/add_asm_generic.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // +build !amd64 5 | 6 | // 对于没有汇编实现的环境, 临时采用Go版本代替 7 | 8 | package add 9 | 10 | func AsmAdd(a, b int) int { 11 | return Add(a, b) 12 | } 13 | 14 | func AsmAddSlice(dst, a, b []int) { 15 | AddSlice(dst, a, b) 16 | } 17 | -------------------------------------------------------------------------------- /examples/ch3.x/add/runme.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // +build ignore 5 | 6 | package main 7 | 8 | import ( 9 | . "." 10 | ) 11 | 12 | func main() { 13 | println("Add(1+2) =", Add(1, 2)) 14 | } 15 | -------------------------------------------------------------------------------- /examples/ch3.x/binary_search/binary_search.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | package bsearch 5 | 6 | func BinarySearch(arr []int, num int) bool 7 | -------------------------------------------------------------------------------- /examples/ch3.x/binary_search/binary_search_amd64.s: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | TEXT ·BinarySearch+0(SB),$0 5 | 6 | start: 7 | MOVQ arr+0(FP), CX 8 | MOVQ len+8(FP), AX 9 | JMP find_index 10 | 11 | find_index: 12 | XORQ DX, DX 13 | MOVQ $2, BX 14 | IDIVQ BX 15 | JMP comp 16 | 17 | comp: 18 | LEAQ (AX * 8), BX 19 | ADDQ BX, CX 20 | MOVQ num+24(FP), DX 21 | CMPQ DX, (CX) 22 | JE found 23 | JG right 24 | JL left 25 | JMP not_found 26 | 27 | left: 28 | CMPQ len+8(FP), $1 29 | JE not_found 30 | MOVQ AX, len+8(FP) 31 | JMP start 32 | 33 | right: 34 | CMPQ len+8(FP), $1 35 | JE not_found 36 | MOVQ CX, arr+0(FP) 37 | JMP start 38 | 39 | not_found: 40 | MOVQ $0, ret+32(FP) 41 | RET 42 | 43 | found: 44 | MOVQ $1, ret+32(FP) 45 | RET 46 | -------------------------------------------------------------------------------- /examples/ch3.x/binary_search/binary_search_test.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | package bsearch 5 | 6 | import "testing" 7 | 8 | func TestBinarySearch(t *testing.T) { 9 | data := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10} 10 | 11 | if result := BinarySearch(data, 8); result != true { 12 | t.Errorf("Expected true value for binary search.") 13 | } 14 | 15 | if result := BinarySearch(data, 1); result != true { 16 | t.Errorf("Expected true value for binary search.") 17 | } 18 | 19 | if result := BinarySearch(data, 10); result != true { 20 | t.Errorf("Expected true value for binary search.") 21 | } 22 | 23 | if result := BinarySearch(data, 12); result != false { 24 | t.Errorf("Expected false value for binary search.") 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /examples/ch3.x/cfun/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | /* 4 | #include 5 | 6 | int64_t myadd(int64_t a, int64_t b) { 7 | return a+b; 8 | } 9 | */ 10 | import "C" 11 | 12 | import ( 13 | "asmpkg" 14 | "fmt" 15 | "runtime" 16 | "unsafe" 17 | ) 18 | 19 | func main() { 20 | if runtime.GOOS == "darwin" { 21 | asmpkg.SyscallWrite_Darwin(1, "hello syscall!\n") 22 | } 23 | if runtime.GOOS == "linux" { 24 | asmpkg.SyscallWrite_Linux(1, "hello syscall!\n") 25 | } 26 | 27 | if runtime.GOOS == "windows" { 28 | fmt.Println(asmpkg.CallCAdd_Win64_ABI( 29 | uintptr(unsafe.Pointer(C.myadd)), 30 | 123, 456, 31 | )) 32 | } else { 33 | fmt.Println(asmpkg.CallCAdd_SystemV_ABI( 34 | uintptr(unsafe.Pointer(C.myadd)), 35 | 123, 456, 36 | )) 37 | } 38 | 39 | var dst = make([]byte, 32) 40 | var src = []byte("1234567890123456789012345678901234567890") 41 | asmpkg.CopySlice_AVX2(dst, src, 32) 42 | fmt.Println(string(dst)) 43 | } 44 | -------------------------------------------------------------------------------- /examples/ch3.x/cfun/vendor/asmpkg/asmpkg.go: -------------------------------------------------------------------------------- 1 | package asmpkg 2 | 3 | func CallCAdd_SystemV_ABI(cfun uintptr, a, b int64) int64 4 | func CallCAdd_Win64_ABI(cfun uintptr, a, b int64) int64 5 | 6 | func SyscallWrite_Darwin(fd int, msg string) int 7 | func SyscallWrite_Linux(fd int, msg string) int 8 | func SyscallWrite_Windows(fd int, msg string) int 9 | 10 | func CopySlice_AVX2(dst, src []byte, len int) 11 | -------------------------------------------------------------------------------- /examples/ch3.x/globalvar/asm_amd64.s: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | #include "textflag.h" 5 | 6 | // func GetPkgValue() int 7 | TEXT ·GetPkgValue(SB), NOSPLIT, $0-8 8 | MOVQ ·gopkgValue(SB), AX 9 | MOVQ AX, ret+0(FP) 10 | RET 11 | 12 | // func GetPkgInfo() PkgInfo 13 | TEXT ·GetPkgInfo(SB), NOSPLIT, $0-24 14 | MOVBLZX ·gInfo+0(SB), AX // .V0 byte 15 | MOVQ AX, ret+0(FP) 16 | MOVWLZX ·gInfo+2(SB), AX // .V1 uint16 17 | MOVQ AX, ret+2(FP) 18 | MOVLQZX ·gInfo+4(SB), AX // .V2 int32 19 | MOVQ AX, ret+4(FP) 20 | MOVQ ·gInfo+8(SB), AX // .V3 int32 21 | MOVQ AX, ret+8(FP) 22 | MOVBLZX ·gInfo+(16+0)(SB), AX // .V4 bool 23 | MOVQ AX, ret+(16+0)(FP) 24 | MOVBLZX ·gInfo+(16+1)(SB), AX // .V5 bool 25 | MOVQ AX, ret+(16+1)(FP) 26 | RET 27 | -------------------------------------------------------------------------------- /examples/ch3.x/globalvar/globalvar.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // 汇编中访问Go中定义的全局变量 5 | 6 | package globalvar 7 | 8 | var gopkgValue int = 42 9 | 10 | type PkgInfo struct { 11 | V0 byte 12 | V1 uint16 13 | V2 int32 14 | V3 int64 15 | V4 bool 16 | V5 bool 17 | } 18 | 19 | var gInfo PkgInfo 20 | 21 | func init() { 22 | gInfo.V0 = 101 23 | gInfo.V1 = 102 24 | gInfo.V2 = 103 25 | gInfo.V3 = 104 26 | gInfo.V4 = true 27 | gInfo.V5 = false 28 | } 29 | 30 | func GetPkgValue() int 31 | 32 | func GetPkgInfo() PkgInfo 33 | -------------------------------------------------------------------------------- /examples/ch3.x/globalvar/runme.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // +build ignore 5 | 6 | package main 7 | 8 | import ( 9 | "fmt" 10 | 11 | . "." 12 | ) 13 | 14 | func main() { 15 | fmt.Println(GetPkgValue()) 16 | fmt.Println(GetPkgInfo()) 17 | } 18 | -------------------------------------------------------------------------------- /examples/ch3.x/hello/hello.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | package hello 5 | 6 | var text = "你好, 世界, 包变量\n" 7 | 8 | func PrintHelloWorld() 9 | func PrintHelloWorld_zh() 10 | func PrintHelloWorld_var() 11 | -------------------------------------------------------------------------------- /examples/ch3.x/hello/runme.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // +build ignore 5 | 6 | package main 7 | 8 | import ( 9 | "fmt" 10 | 11 | . "." 12 | ) 13 | 14 | func main() { 15 | s := "你好, 世界!\n" 16 | fmt.Printf("%d: %x\n", len(s), s) 17 | PrintHelloWorld() 18 | PrintHelloWorld_zh() 19 | PrintHelloWorld_var() 20 | } 21 | -------------------------------------------------------------------------------- /examples/ch3.x/ifelse/ifelse.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // Go版本, 支持内联优化 5 | 6 | package ifelse 7 | 8 | func If(ok bool, a, b int) int { 9 | if ok { 10 | return a 11 | } 12 | return b 13 | } 14 | 15 | func AsmIf(ok bool, a, b int) int 16 | -------------------------------------------------------------------------------- /examples/ch3.x/ifelse/ifelse_ams_amd64.s: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | #include "textflag.h" 5 | 6 | // 7 | // https://github.com/golang/go/issues/14288 8 | // 9 | // from rsc: 10 | // But expanding what I said yesterday just a bit: 11 | // never use MOVB or MOVW with a register destination, 12 | // since it's inefficient (it's a read-modify-write on the target register). 13 | // Instead use MOVL for reg->reg and use MOVBLZX or MOVWLZX for mem->reg; 14 | // those are pure writes on the target register. 15 | // 16 | // 因此, 加载bool型参数到寄存器时, 建议使用 MOVBLZX. 17 | // 如果使用 MOVB 的话, go test 虽然通过了, 18 | // 但是 go run runme.go 则出现错误结果. 19 | // 20 | 21 | // func AsmIf(ok bool, a, b int) int 22 | TEXT ·AsmIf(SB), NOSPLIT, $0-32 23 | MOVBQZX ok+0(FP), AX // ok 24 | MOVQ a+8(FP), BX // a 25 | MOVQ b+16(FP), CX // b 26 | CMPQ AX, $0 // test ok 27 | JEQ 3(PC) // if !ok, skip 2 line 28 | MOVQ BX, ret+24(FP) // return a 29 | RET 30 | MOVQ CX, ret+24(FP) // return b 31 | RET 32 | -------------------------------------------------------------------------------- /examples/ch3.x/ifelse/ifelse_test.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // go test -bench=. 5 | 6 | package ifelse 7 | 8 | import ( 9 | "testing" 10 | ) 11 | 12 | func TestMin(t *testing.T) { 13 | t.Run("go", func(t *testing.T) { 14 | if x := If(true, 1, 2); x != 1 { 15 | t.Fatalf("expect = %d, got = %d", 1, x) 16 | } 17 | if x := If(false, 1, 2); x != 2 { 18 | t.Fatalf("expect = %d, got = %d", 2, x) 19 | } 20 | }) 21 | t.Run("asm", func(t *testing.T) { 22 | if x := AsmIf(true, 1, 2); x != 1 { 23 | t.Fatalf("expect = %d, got = %d", 1, x) 24 | } 25 | if x := AsmIf(false, 1, 2); x != 2 { 26 | t.Fatalf("expect = %d, got = %d", 2, x) 27 | } 28 | if x := AsmIf(false, 2, 1); x != 1 { 29 | t.Fatalf("expect = %d, got = %d", 1, x) 30 | } 31 | }) 32 | } 33 | -------------------------------------------------------------------------------- /examples/ch3.x/ifelse/runme.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // +build ignore 5 | 6 | package main 7 | 8 | import ( 9 | . "." 10 | ) 11 | 12 | func main() { 13 | println("If(true, 1, 2) =", If(true, 1, 2)) 14 | println("If(false, 1, 2) =", If(false, 1, 2)) 15 | println("AsmIf(true, 1, 2) =", AsmIf(true, 1, 2)) 16 | println("AsmIf(false, 1, 2) =", AsmIf(false, 1, 2)) 17 | println("AsmIf(false, 2, 1) =", AsmIf(false, 2, 1)) 18 | } 19 | -------------------------------------------------------------------------------- /examples/ch3.x/instr/bench_test.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | package instr 5 | 6 | import "testing" 7 | 8 | var g int64 9 | 10 | func BenchmarkSum(b *testing.B) { 11 | ns := []int64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10} 12 | for i := 0; i < b.N; i++ { 13 | g = Sum(ns) 14 | } 15 | } 16 | 17 | func BenchmarkSum2(b *testing.B) { 18 | ns := []int64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10} 19 | for i := 0; i < b.N; i++ { 20 | g = Sum2(ns) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /examples/ch3.x/instr/instr.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | package instr 5 | 6 | func Add(n, m int64) int64 { 7 | return n + m 8 | } 9 | 10 | func Add2(n, m int64) int64 11 | 12 | // BSF returns the index of the least significant set bit, 13 | // or -1 if the input contains no set bits. 14 | func BSF(n int64) int 15 | 16 | func BSF32(n int32) int32 17 | 18 | func Sum(s []int64) int64 { 19 | var ss int64 20 | for _, n := range s { 21 | ss += n 22 | } 23 | return ss 24 | } 25 | 26 | func Sum2(s []int64) int64 27 | -------------------------------------------------------------------------------- /examples/ch3.x/instr/instr_amd64.s: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | #include "textflag.h" 5 | 6 | // func Add2(n, m int64) int32 7 | TEXT ·Add2(SB), NOSPLIT, $0-24 8 | MOVQ n+0(FP), AX 9 | MOVQ m+8(FP), BX 10 | ADDQ AX, BX 11 | MOVQ BX, ret+16(FP) 12 | RET 13 | 14 | // func BSF(n int64) int 15 | TEXT ·BSF(SB), NOSPLIT, $0 16 | BSFQ n+0(FP), AX 17 | JEQ allZero 18 | MOVQ AX, ret+8(FP) 19 | RET 20 | 21 | allZero: 22 | MOVQ $-1, ret+8(FP) 23 | RET 24 | 25 | // func BSF32(n int32) int32 26 | TEXT ·BSF32(SB), NOSPLIT, $0 27 | BSFL n+0(FP), AX 28 | JEQ allZero32 29 | MOVL AX, ret+8(FP) 30 | RET 31 | 32 | allZero32: 33 | MOVL $-1, ret+8(FP) 34 | RET 35 | 36 | // func Sum2(s []int64) int64 37 | TEXT ·Sum2(SB), NOSPLIT, $0 38 | MOVQ $0, DX 39 | MOVQ s_base+0(FP), AX 40 | MOVQ s_len+8(FP), DI 41 | MOVQ $0, CX 42 | CMPQ CX, DI 43 | JGE Sum2End 44 | 45 | Sum2Loop: 46 | MOVQ (AX), BP 47 | ADDQ BP, DX 48 | ADDQ $8, AX 49 | INCQ CX 50 | CMPQ CX, DI 51 | JL Sum2Loop 52 | 53 | Sum2End: 54 | MOVQ DX, ret+24(FP) 55 | RET 56 | 57 | // vim: set ft=txt: 58 | -------------------------------------------------------------------------------- /examples/ch3.x/loop/loop.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // Go版本, 支持内联优化 5 | 6 | package loop 7 | 8 | func LoopAdd(cnt, v0, step int) int { 9 | result := v0 10 | for i := 0; i < cnt; i++ { 11 | result += step 12 | } 13 | return result 14 | } 15 | 16 | func AsmLoopAdd(cnt, v0, step int) int 17 | -------------------------------------------------------------------------------- /examples/ch3.x/loop/loop_asm_amd64.s: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | #include "textflag.h" 5 | 6 | // func AsmLoopAdd(cnt, v0, step int) int 7 | TEXT ·AsmLoopAdd(SB), NOSPLIT, $0-32 8 | MOVQ cnt+0(FP), AX // cnt 9 | MOVQ v0+8(FP), BX // v0 10 | MOVQ step+16(FP), CX // step 11 | 12 | loop: 13 | CMPQ AX, $0 // compare cnt,0 14 | JLE end // if cnt <= 0: go end 15 | DECQ AX // cnt-- 16 | ADDQ CX, BX // v0 += step 17 | JMP loop // goto loop 18 | 19 | end: 20 | MOVQ BX, ret+24(FP) // return v0 21 | RET 22 | -------------------------------------------------------------------------------- /examples/ch3.x/loop/runme.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // +build ignore 5 | 6 | package main 7 | 8 | import ( 9 | . "." 10 | ) 11 | 12 | func main() { 13 | println("LoopAdd(100,0,1) =", LoopAdd(100, 0, 1)) 14 | println("LoopAdd(100,0,2) =", LoopAdd(100, 0, 2)) 15 | println("LoopAdd(100,200,-1) =", LoopAdd(100, 200, -1)) 16 | println("LoopAdd(100,0,-1) =", LoopAdd(100, 0, -1)) 17 | } 18 | -------------------------------------------------------------------------------- /examples/ch3.x/min/min.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // Go版本, 支持内联优化 5 | 6 | package min 7 | 8 | func Min(a, b int) int { 9 | if a < b { 10 | return a 11 | } 12 | return b 13 | } 14 | 15 | //go:noinline 16 | func MinNoInline(a, b int) int { 17 | if a < b { 18 | return a 19 | } 20 | return b 21 | } 22 | 23 | func Max(a, b int) int { 24 | if a > b { 25 | return a 26 | } 27 | return b 28 | } 29 | 30 | func AsmMin(a, b int) int 31 | func AsmMax(a, b int) int 32 | -------------------------------------------------------------------------------- /examples/ch3.x/min/min_asm_amd64.s: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | #include "textflag.h" 5 | 6 | // func AsmMin(a, b int) int 7 | TEXT ·AsmMin(SB), NOSPLIT, $0-24 8 | MOVQ a+0(FP), AX // a 9 | MOVQ b+8(FP), BX // b 10 | CMPQ AX, BX // compare a, b 11 | JGT 3(PC) // if a>b, skip 2 line 12 | MOVQ AX, ret+16(FP) // return a 13 | RET 14 | MOVQ BX, ret+16(FP) // return b 15 | RET 16 | 17 | // func AsmMax(a, b int) int 18 | TEXT ·AsmMax(SB), NOSPLIT, $0-24 19 | MOVQ a+0(FP), AX // a 20 | MOVQ b+8(FP), BX // b 21 | CMPQ AX, BX // compare a, b 22 | JLT 3(PC) // if a. 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // +build ignore 5 | 6 | package main 7 | 8 | import ( 9 | . "." 10 | ) 11 | 12 | func main() { 13 | println("Min(1,2) =", Min(1, 2)) 14 | } 15 | -------------------------------------------------------------------------------- /examples/ch3.x/slice/runme.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // +build ignore 5 | 6 | package main 7 | 8 | import ( 9 | . "." 10 | ) 11 | 12 | func main() { 13 | println("SumIntSlice([]int{1,2,3}) =", SumIntSlice([]int{1, 2, 3})) 14 | println("AsmSumIntSlice([]int{1,2,3}) =", AsmSumIntSlice([]int{1, 2, 3})) 15 | } 16 | -------------------------------------------------------------------------------- /examples/ch3.x/slice/slice.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | // Go版本, 支持内联优化 5 | 6 | package slice 7 | 8 | func SumIntSlice(s []int) int { 9 | var sum int 10 | for _, v := range s { 11 | sum += v 12 | } 13 | return sum 14 | } 15 | 16 | func SumFloat32Slice(s []float32) float32 { 17 | var sum float32 18 | for _, v := range s { 19 | sum += v 20 | } 21 | return sum 22 | } 23 | 24 | func SumFloat64Slice(s []float64) float64 { 25 | var sum float64 26 | for _, v := range s { 27 | sum += v 28 | } 29 | return sum 30 | } 31 | 32 | func AsmSumInt16Slice(v []int16) int16 33 | 34 | func AsmSumIntSlice(s []int) int 35 | func AsmSumIntSliceV2(s []int) int 36 | -------------------------------------------------------------------------------- /examples/ch3.x/stackmap/stackmap.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | package stackmap 5 | 6 | func X(b []byte) []byte 7 | 8 | //func X(b []byte) []byte { 9 | // if len(b) == cap(b) { 10 | // b = growSlice(b) 11 | // } 12 | // b = b[:len(b)+1] 13 | // b[len(b)-1] = 3 14 | // return b 15 | //} 16 | 17 | func growSlice(b []byte) []byte { 18 | newCap := 10 19 | if cap(b) > 5 { 20 | newCap = cap(b) * 2 21 | } 22 | b1 := make([]byte, len(b), newCap) 23 | copy(b1, b) 24 | return b1 25 | } 26 | -------------------------------------------------------------------------------- /examples/ch3.x/stackmap/stackmap_amd64.s: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | #include "funcdata.h" 5 | #include "textflag.h" 6 | 7 | // func X(b []byte) []byte 8 | TEXT ·X(SB), $48-48 9 | MOVQ b_base+0(FP), BX 10 | MOVQ b_len+8(FP), CX 11 | MOVQ b_cap+16(FP), DX 12 | 13 | CMPQ CX, DX 14 | JL afterGrow 15 | 16 | // Set up the growSlice call. 17 | MOVQ BX, gs_base-48(SP) 18 | MOVQ CX, gs_len-40(SP) 19 | MOVQ DX, gs_cap-32(SP) 20 | 21 | CALL ·growSlice(SB) 22 | 23 | MOVQ gs_base-24(SP), BX 24 | MOVQ gs_len-16(SP), CX 25 | MOVQ gs_cap-8(SP), DX 26 | 27 | afterGrow: 28 | // At this point, we have adequate capacity to increase len + 1 and the 29 | // following register scheme: 30 | // BX - b_base 31 | // CX - b_len 32 | // DX - b_cap 33 | 34 | // Write base/cap results. 35 | MOVQ BX, ret_base+24(FP) 36 | MOVQ DX, ret_cap+40(FP) 37 | 38 | // Write new element to b and increment the length. 39 | LEAQ (BX)(CX*1), BX 40 | MOVB $3, (BX) 41 | ADDQ $1, CX 42 | MOVQ CX, ret_len+32(FP) 43 | 44 | RET 45 | -------------------------------------------------------------------------------- /examples/ch3.x/stackmap/stackmap_test.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | package stackmap 5 | 6 | import ( 7 | "bytes" 8 | "testing" 9 | ) 10 | 11 | func TestX(t *testing.T) { 12 | b := make([]byte, 0, 3) 13 | 14 | for _, want := range [][]byte{ 15 | mkSlice(3, 3), 16 | mkSlice(3, 3, 3), 17 | mkSlice(3, 3, 3, 3), 18 | mkSlice(10, 3, 3, 3, 3), 19 | mkSlice(10, 3, 3, 3, 3, 3), 20 | mkSlice(10, 3, 3, 3, 3, 3, 3), 21 | mkSlice(10, 3, 3, 3, 3, 3, 3, 3), 22 | mkSlice(10, 3, 3, 3, 3, 3, 3, 3, 3), 23 | mkSlice(10, 3, 3, 3, 3, 3, 3, 3, 3, 3), 24 | mkSlice(10, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3), 25 | mkSlice(20, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3), 26 | } { 27 | b = X(b) 28 | if !slicesEqual(b, want) { 29 | t.Fatalf("got %v[cap=%d]; want %v[cap=%d]", 30 | b, cap(b), want, cap(want)) 31 | } 32 | } 33 | } 34 | 35 | func mkSlice(cap int, vs ...byte) []byte { 36 | b1 := make([]byte, 0, cap) 37 | for _, v := range vs { 38 | b1 = append(b1, v) 39 | } 40 | return b1 41 | } 42 | func slicesEqual(b0, b1 []byte) bool { 43 | if cap(b0) != cap(b1) { 44 | return false 45 | } 46 | return bytes.Equal(b0, b1) 47 | } 48 | -------------------------------------------------------------------------------- /examples/ch3.x/sum/sum.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | package sum 5 | 6 | func Sum(a int, b int) int 7 | -------------------------------------------------------------------------------- /examples/ch3.x/sum/sum_amd64.s: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | TEXT ·Sum+0(SB),$0 5 | MOVQ a+0(FP), BX 6 | MOVQ b+8(FP), BP 7 | ADDQ BP, BX 8 | MOVQ BX, return+16(FP) 9 | RET 10 | -------------------------------------------------------------------------------- /examples/ch3.x/sum/sum_test.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | package sum 5 | 6 | import "testing" 7 | 8 | func TestSum(t *testing.T) { 9 | result := Sum(1, 1) 10 | 11 | if result != 2 { 12 | t.Errorf("%d does not equal 2", result) 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /examples/ch3.x/vector/sum_amd64.s: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | TEXT ·SumVec+0(SB), $0 5 | MOVQ vec1+0(FP), BX // Move the first vector into BX 6 | MOVQ vec2+24(FP), CX // Move the second vector into BX 7 | MOVUPS (BX), X0 8 | MOVUPS (CX), X1 9 | ADDPS X0, X1 10 | MOVUPS X1, result+48(FP) 11 | RET 12 | -------------------------------------------------------------------------------- /examples/ch3.x/vector/vector.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | package vector 5 | 6 | func Find(vec []int, num int) bool 7 | 8 | func SumVec(vec1 []int32, vec2 []int32) [4]int32 9 | -------------------------------------------------------------------------------- /examples/ch3.x/vector/vector_amd64.s: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | TEXT ·Find+0(SB),$0 5 | MOVQ $0, SI // zero the iterator 6 | MOVQ vec+0(FP), BX // BX = &vec[0] 7 | MOVQ vec+8(FP), CX // len(vec) 8 | MOVQ num+24(FP), DX 9 | 10 | start: 11 | CMPQ SI, CX 12 | JG notfound 13 | CMPQ (BX), DX 14 | JNE notequal 15 | JE found 16 | 17 | found: 18 | MOVQ $1, return+32(FP) 19 | RET 20 | 21 | notequal: 22 | INCQ SI 23 | LEAQ +8(BX), BX 24 | JMP start 25 | 26 | notfound: 27 | MOVQ $0, return+32(FP) 28 | RET 29 | -------------------------------------------------------------------------------- /examples/ch3.x/vector/vector_test.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 ChaiShushan . 2 | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ 3 | 4 | package vector 5 | 6 | import "testing" 7 | 8 | func TestFind(t *testing.T) { 9 | vec := []int{1, 2, 3, 4, 5, 6, 7, 8} 10 | if result := Find(vec, 5); result != true { 11 | t.Errorf("Could not find number in vector, got: %v", result) 12 | } 13 | 14 | if result := Find(vec, 10); result != false { 15 | t.Errorf("Returned true when false was expected") 16 | } 17 | } 18 | 19 | func TestSum(t *testing.T) { 20 | vec1 := []int32{1, 2, 3, 5} 21 | vec2 := []int32{1, 2, 3, 5} 22 | 23 | result := SumVec(vec1, vec2) 24 | 25 | if result[0] != 2 { 26 | t.Errorf("Expected 2, got %v, result was: %v", result[0], result) 27 | } 28 | 29 | if result[1] != 4 { 30 | t.Errorf("Expected 4, got %v, result was: %v", result[0], result) 31 | } 32 | 33 | if result[2] != 6 { 34 | t.Errorf("Expected 6, got %v, result was: %v", result[0], result) 35 | } 36 | 37 | if result[3] != 10 { 38 | t.Errorf("Expected 10, got %v, result was: %v", result[0], result) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /examples/ch4.1/hello-client-v1/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "net/rpc" 7 | ) 8 | 9 | func main() { 10 | client, err := rpc.Dial("tcp", "localhost:1234") 11 | if err != nil { 12 | log.Fatal("dialing:", err) 13 | } 14 | 15 | var reply string 16 | err = client.Call("HelloService.Hello", "hello", &reply) 17 | if err != nil { 18 | log.Fatal(err) 19 | } 20 | 21 | fmt.Println(reply) 22 | } 23 | -------------------------------------------------------------------------------- /examples/ch4.1/hello-server-v1/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "net" 6 | "net/rpc" 7 | ) 8 | 9 | type HelloService struct{} 10 | 11 | func (p *HelloService) Hello(request string, reply *string) error { 12 | *reply = "HelloService.Hello:" + request 13 | return nil 14 | } 15 | 16 | func main() { 17 | rpc.Register(new(HelloService)) 18 | 19 | listener, err := net.Listen("tcp", ":1234") 20 | if err != nil { 21 | log.Fatal("ListenTCP error:", err) 22 | } 23 | 24 | conn, err := listener.Accept() 25 | if err != nil { 26 | log.Fatal("Accept error:", err) 27 | } 28 | 29 | rpc.ServeConn(conn) 30 | } 31 | -------------------------------------------------------------------------------- /examples/ch4.1/hello-service-v2/api/hello.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import "net/rpc" 4 | 5 | const HelloServiceName = "path/to/pkg.HelloService" 6 | 7 | type HelloServiceInterface = interface { 8 | Hello(request string, reply *string) error 9 | } 10 | 11 | func RegisterHelloService(svc HelloServiceInterface) error { 12 | return rpc.RegisterName(HelloServiceName, svc) 13 | } 14 | 15 | type HelloServiceClient struct { 16 | *rpc.Client 17 | } 18 | 19 | var _ HelloServiceInterface = (*HelloServiceClient)(nil) 20 | 21 | func DialHelloService(network, address string) (*HelloServiceClient, error) { 22 | c, err := rpc.Dial(network, address) 23 | if err != nil { 24 | return nil, err 25 | } 26 | return &HelloServiceClient{Client: c}, nil 27 | } 28 | 29 | func (p *HelloServiceClient) Hello(request string, reply *string) error { 30 | return p.Client.Call(HelloServiceName+".Hello", request, reply) 31 | } 32 | -------------------------------------------------------------------------------- /examples/ch4.1/hello-service-v2/client/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | 7 | "gobook.examples/ch4-01-rpc-intro/hello-service-v2/api" 8 | ) 9 | 10 | type HelloService struct{} 11 | 12 | func (p *HelloService) Hello(request string, reply *string) error { 13 | *reply = "hello:" + request 14 | return nil 15 | } 16 | 17 | func main() { 18 | 19 | client, err := api.DialHelloService("tcp", "localhost:1234") 20 | if err != nil { 21 | log.Fatal("dialing:", err) 22 | } 23 | 24 | var reply string 25 | err = client.Hello("hello", &reply) 26 | if err != nil { 27 | log.Fatal(err) 28 | } 29 | 30 | fmt.Println(reply) 31 | } 32 | -------------------------------------------------------------------------------- /examples/ch4.1/hello-service-v2/server/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "net" 6 | "net/rpc" 7 | 8 | "gobook.examples/ch4-01-rpc-intro/hello-service-v2/api" 9 | ) 10 | 11 | type HelloService struct{} 12 | 13 | func (p *HelloService) Hello(request string, reply *string) error { 14 | *reply = "hello:" + request 15 | return nil 16 | } 17 | 18 | func main() { 19 | api.RegisterHelloService(new(HelloService)) 20 | 21 | listener, err := net.Listen("tcp", ":1234") 22 | if err != nil { 23 | log.Fatal("ListenTCP error:", err) 24 | } 25 | 26 | for { 27 | conn, err := listener.Accept() 28 | if err != nil { 29 | log.Fatal("Accept error:", err) 30 | } 31 | 32 | go rpc.ServeConn(conn) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /examples/ch4.1/hello-service-v3/client/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "log" 7 | "net" 8 | "net/rpc" 9 | "net/rpc/jsonrpc" 10 | ) 11 | 12 | var flagAddr = flag.String("addr", "localhost:1234", "server address") 13 | 14 | func main() { 15 | flag.Parse() 16 | 17 | // nc localhost 1234 18 | // {"method":"HelloService.Hello","params":["hello"],"id":0} 19 | // echo -e '{"method":"HelloService.Hello","params":["hello2222"],"id":3}' | nc localhost 1234 20 | // echo -e '{"method":"HelloService.Hello","params":["hello2222"],"id":3}{"method":"HelloService.Hello","params":["hello33"],"id":4}' | nc localhost 1234 21 | 22 | conn, err := net.Dial("tcp", *flagAddr) 23 | if err != nil { 24 | log.Fatal("net.Dial:", err) 25 | } 26 | 27 | client := rpc.NewClientWithCodec(jsonrpc.NewClientCodec(conn)) 28 | 29 | var reply string 30 | err = client.Call("HelloService.Hello", "hello", &reply) 31 | if err != nil { 32 | log.Fatal(err) 33 | } 34 | 35 | fmt.Println(reply) 36 | } 37 | -------------------------------------------------------------------------------- /examples/ch4.1/hello-service-v3/server-on-http/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "io" 5 | "net/http" 6 | "net/rpc" 7 | "net/rpc/jsonrpc" 8 | ) 9 | 10 | type HelloService struct{} 11 | 12 | func (p *HelloService) Hello(request string, reply *string) error { 13 | *reply = "hello:" + request 14 | return nil 15 | } 16 | 17 | func main() { 18 | rpc.RegisterName("HelloService", new(HelloService)) 19 | 20 | // curl localhost:1234/jsonrpc --data '{"method":"HelloService.Hello","params":["hello"],"id":0}' 21 | http.HandleFunc("/jsonrpc", func(w http.ResponseWriter, r *http.Request) { 22 | var conn io.ReadWriteCloser = struct { 23 | io.Writer 24 | io.ReadCloser 25 | }{ 26 | ReadCloser: r.Body, 27 | Writer: w, 28 | } 29 | 30 | rpc.ServeRequest(jsonrpc.NewServerCodec(conn)) 31 | }) 32 | 33 | http.ListenAndServe(":1234", nil) 34 | } 35 | -------------------------------------------------------------------------------- /examples/ch4.1/hello-service-v3/server/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "log" 7 | "net" 8 | "net/rpc" 9 | "net/rpc/jsonrpc" 10 | ) 11 | 12 | type HelloService struct{} 13 | 14 | func (p *HelloService) Hello(request string, reply *string) error { 15 | *reply = "hello:" + request 16 | return nil 17 | } 18 | 19 | var flagPort = flag.Int("port", 1234, "listen port") 20 | 21 | func main() { 22 | flag.Parse() 23 | 24 | rpc.RegisterName("HelloService", new(HelloService)) 25 | 26 | // nc -l 2399 27 | listener, err := net.Listen("tcp", fmt.Sprintf(":%d", *flagPort)) 28 | if err != nil { 29 | log.Fatal("ListenTCP error:", err) 30 | } 31 | 32 | for { 33 | conn, err := listener.Accept() 34 | if err != nil { 35 | log.Fatal("Accept error:", err) 36 | } 37 | 38 | go rpc.ServeCodec(jsonrpc.NewServerCodec(conn)) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /examples/ch4.2/hello-server/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "net" 6 | "net/rpc" 7 | 8 | pb "gobook.examples/ch4-02-proto/hello.pb" 9 | ) 10 | 11 | type HelloService struct{} 12 | 13 | func (p *HelloService) Hello(request pb.String, reply *pb.String) error { 14 | reply.Value = "hello:" + request.GetValue() 15 | return nil 16 | } 17 | 18 | func main() { 19 | rpc.Register(new(HelloService)) 20 | 21 | listener, err := net.Listen("tcp", ":1234") 22 | if err != nil { 23 | log.Fatal("ListenTCP error:", err) 24 | } 25 | 26 | for { 27 | conn, err := listener.Accept() 28 | if err != nil { 29 | log.Fatal("Accept error:", err) 30 | } 31 | 32 | go rpc.ServeConn(conn) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /examples/ch4.2/hello.pb/Makefile: -------------------------------------------------------------------------------- 1 | generate: 2 | protoc --go_out=. hello.proto 3 | 4 | clean: 5 | -rm *.pb.go 6 | 7 | -------------------------------------------------------------------------------- /examples/ch4.2/hello.pb/hello.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package hello; 4 | 5 | message String { 6 | string value = 1; 7 | } 8 | 9 | service HelloService { 10 | rpc Hello (String) returns (String); 11 | } 12 | -------------------------------------------------------------------------------- /examples/ch4.3/rpc-auth/client/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "net/rpc" 7 | ) 8 | 9 | func main() { 10 | client, err := rpc.Dial("tcp", "localhost:1234") 11 | if err != nil { 12 | log.Fatal("dialing:", err) 13 | } 14 | 15 | var reply string 16 | 17 | err = client.Call("HelloService.Login", "abc", &reply) 18 | if err != nil { 19 | log.Println(err) 20 | } else { 21 | log.Println("login ok") 22 | } 23 | 24 | err = client.Call("HelloService.Login", "user:password", &reply) 25 | if err != nil { 26 | log.Println(err) 27 | } else { 28 | log.Println("login ok") 29 | } 30 | 31 | err = client.Call("HelloService.Hello", "hello", &reply) 32 | if err != nil { 33 | log.Fatal(err) 34 | } 35 | 36 | fmt.Println(reply) 37 | } 38 | -------------------------------------------------------------------------------- /examples/ch4.3/rpc-auth/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | func main() { 4 | // todo 5 | // tls 6 | } 7 | -------------------------------------------------------------------------------- /examples/ch4.3/rpc-auth/server/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "net" 7 | "net/rpc" 8 | ) 9 | 10 | type HelloService struct { 11 | conn net.Conn 12 | isLogin bool 13 | } 14 | 15 | func ServeHelloService(conn net.Conn) { 16 | p := rpc.NewServer() 17 | p.Register(&HelloService{conn: conn}) 18 | p.ServeConn(conn) 19 | } 20 | 21 | func (p *HelloService) Login(request string, reply *string) error { 22 | if request != "user:password" { 23 | log.Println("login failed") 24 | return fmt.Errorf("auth failed") 25 | } 26 | log.Println("login ok") 27 | p.isLogin = true 28 | return nil 29 | } 30 | 31 | func (p *HelloService) Hello(request string, reply *string) error { 32 | if !p.isLogin { 33 | return fmt.Errorf("please login") 34 | } 35 | *reply = "hello:" + request + ", from" + p.conn.RemoteAddr().String() 36 | return nil 37 | } 38 | 39 | func main() { 40 | listener, err := net.Listen("tcp", ":1234") 41 | if err != nil { 42 | log.Fatal("ListenTCP error:", err) 43 | } 44 | 45 | for { 46 | conn, err := listener.Accept() 47 | if err != nil { 48 | log.Fatal("Accept error:", err) 49 | } 50 | 51 | go ServeHelloService(conn) 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /examples/ch4.3/rpc-context/client/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "net/rpc" 7 | ) 8 | 9 | func main() { 10 | client, err := rpc.Dial("tcp", "localhost:1234") 11 | if err != nil { 12 | log.Fatal("dialing:", err) 13 | } 14 | 15 | var reply string 16 | err = client.Call("HelloService.Hello", "hello", &reply) 17 | if err != nil { 18 | log.Fatal(err) 19 | } 20 | 21 | fmt.Println(reply) 22 | } 23 | -------------------------------------------------------------------------------- /examples/ch4.3/rpc-context/server/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "net" 6 | "net/rpc" 7 | ) 8 | 9 | type HelloService struct { 10 | conn net.Conn 11 | } 12 | 13 | func ServeHelloService(conn net.Conn) { 14 | p := rpc.NewServer() 15 | p.Register(&HelloService{conn: conn}) 16 | p.ServeConn(conn) 17 | } 18 | 19 | func (p *HelloService) Hello(request string, reply *string) error { 20 | *reply = "hello:" + request + ", from" + p.conn.RemoteAddr().String() 21 | return nil 22 | } 23 | 24 | func main() { 25 | listener, err := net.Listen("tcp", ":1234") 26 | if err != nil { 27 | log.Fatal("ListenTCP error:", err) 28 | } 29 | 30 | for { 31 | conn, err := listener.Accept() 32 | if err != nil { 33 | log.Fatal("Accept error:", err) 34 | } 35 | 36 | go ServeHelloService(conn) 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /examples/ch4.3/rpc-reverse/client/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "net" 7 | "net/rpc" 8 | ) 9 | 10 | func main() { 11 | listener, err := net.Listen("tcp", ":1234") 12 | if err != nil { 13 | log.Fatal("ListenTCP error:", err) 14 | } 15 | 16 | clientChan := make(chan *rpc.Client) 17 | 18 | go func() { 19 | for { 20 | conn, err := listener.Accept() 21 | if err != nil { 22 | log.Fatal("Accept error:", err) 23 | } 24 | 25 | clientChan <- rpc.NewClient(conn) 26 | } 27 | }() 28 | 29 | client := <-clientChan 30 | defer client.Close() 31 | 32 | var reply string 33 | err = client.Call("HelloService.Hello", "hello", &reply) 34 | if err != nil { 35 | log.Fatal(err) 36 | } 37 | 38 | fmt.Println(reply) 39 | } 40 | -------------------------------------------------------------------------------- /examples/ch4.3/rpc-reverse/server/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net" 5 | "net/rpc" 6 | "time" 7 | ) 8 | 9 | type HelloService struct{} 10 | 11 | func (p *HelloService) Hello(request string, reply *string) error { 12 | *reply = "hello:" + request 13 | return nil 14 | } 15 | 16 | func main() { 17 | rpc.Register(new(HelloService)) 18 | 19 | for { 20 | conn, _ := net.Dial("tcp", "localhost:1234") 21 | if conn == nil { 22 | time.Sleep(time.Second) 23 | continue 24 | } 25 | 26 | rpc.ServeConn(conn) 27 | conn.Close() 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /examples/ch4.4/1/client/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "log" 7 | 8 | "google.golang.org/grpc" 9 | 10 | hs "ch4.4-1/helloservice" 11 | ) 12 | 13 | func main() { 14 | conn, err := grpc.Dial("localhost:1234", grpc.WithInsecure()) 15 | if err != nil { 16 | log.Fatal(err) 17 | } 18 | defer conn.Close() 19 | 20 | client := hs.NewHelloServiceClient(conn) 21 | reply, err := client.Hello(context.Background(), &hs.String{Value: "hello"}) 22 | if err != nil { 23 | log.Fatal(err) 24 | } 25 | fmt.Println(reply.GetValue()) 26 | } 27 | -------------------------------------------------------------------------------- /examples/ch4.4/1/helloservice/hello.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package helloservice; 4 | 5 | message String { 6 | string value = 1; 7 | } 8 | 9 | service HelloService { 10 | rpc Hello (String) returns (String); 11 | } 12 | 13 | //protoc --go_out=plugins=grpc:. hello.proto -------------------------------------------------------------------------------- /examples/ch4.4/1/server/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "log" 6 | "net" 7 | 8 | "google.golang.org/grpc" 9 | 10 | hs "ch4.4-1/helloservice" 11 | ) 12 | 13 | type HelloServiceImpl struct{} 14 | 15 | func (p *HelloServiceImpl) Hello( 16 | ctx context.Context, args *hs.String, 17 | ) (*hs.String, error) { 18 | reply := &hs.String{Value: "hello:" + args.GetValue()} 19 | return reply, nil 20 | } 21 | 22 | func main() { 23 | grpcServer := grpc.NewServer() 24 | hs.RegisterHelloServiceServer(grpcServer, new(HelloServiceImpl)) 25 | 26 | lis, err := net.Listen("tcp", ":1234") 27 | if err != nil { 28 | log.Fatal(err) 29 | } 30 | grpcServer.Serve(lis) 31 | } 32 | -------------------------------------------------------------------------------- /examples/ch4.4/2/HelloService/hello.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package HelloService; 4 | 5 | message String { 6 | string value = 1; 7 | } 8 | 9 | service HelloService { 10 | rpc Hello (String) returns (String); 11 | rpc Channel (stream String) returns (stream String); 12 | } 13 | 14 | //protoc --go_out=plugins=grpc:. hello.proto -------------------------------------------------------------------------------- /examples/ch4.4/2/client/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "io" 7 | "log" 8 | "time" 9 | 10 | "google.golang.org/grpc" 11 | 12 | hs "ch4.4-2/HelloService" 13 | ) 14 | 15 | func main() { 16 | conn, err := grpc.Dial("localhost:1234", grpc.WithInsecure()) 17 | if err != nil { 18 | log.Fatal(err) 19 | } 20 | defer conn.Close() 21 | 22 | client := hs.NewHelloServiceClient(conn) 23 | reply, err := client.Hello(context.Background(), &hs.String{Value: "hello"}) 24 | if err != nil { 25 | log.Fatal(err) 26 | } 27 | fmt.Println(reply.GetValue()) 28 | 29 | //grpc stream 30 | stream, err := client.Channel(context.Background()) 31 | if err != nil { 32 | log.Fatal(err) 33 | } 34 | 35 | go func() { 36 | for { 37 | if err := stream.Send(&hs.String{Value: "hi"}); err != nil { 38 | log.Fatal(err) 39 | } 40 | time.Sleep(time.Second) 41 | } 42 | }() 43 | 44 | for { 45 | reply, err := stream.Recv() 46 | if err != nil { 47 | if err == io.EOF { 48 | break 49 | } 50 | log.Fatal(err) 51 | } 52 | fmt.Println(reply.GetValue()) 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /examples/ch4.4/2/server/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "io" 6 | "log" 7 | "net" 8 | 9 | "google.golang.org/grpc" 10 | 11 | hs "ch4.4-2/HelloService" 12 | ) 13 | 14 | type HelloServiceImpl struct{} 15 | 16 | func (p *HelloServiceImpl) Hello( 17 | ctx context.Context, args *hs.String, 18 | ) (*hs.String, error) { 19 | reply := &hs.String{Value: "hello:" + args.GetValue()} 20 | return reply, nil 21 | } 22 | 23 | //grpc stream 24 | func (p *HelloServiceImpl) Channel(stream hs.HelloService_ChannelServer) error { 25 | for { 26 | args, err := stream.Recv() 27 | if err != nil { 28 | if err == io.EOF { 29 | return nil 30 | } 31 | return err 32 | } 33 | 34 | reply := &hs.String{Value: "hello:" + args.GetValue()} 35 | 36 | err = stream.Send(reply) 37 | if err != nil { 38 | return err 39 | } 40 | } 41 | } 42 | 43 | func main() { 44 | grpcServer := grpc.NewServer() 45 | hs.RegisterHelloServiceServer(grpcServer, new(HelloServiceImpl)) 46 | 47 | lis, err := net.Listen("tcp", ":1234") 48 | if err != nil { 49 | log.Fatal(err) 50 | } 51 | 52 | grpcServer.Serve(lis) 53 | } 54 | -------------------------------------------------------------------------------- /examples/ch4.4/3/clientpub/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "log" 6 | 7 | "google.golang.org/grpc" 8 | 9 | pb "ch4.4-3/pubsubservice" 10 | ) 11 | 12 | func main() { 13 | conn, err := grpc.Dial("localhost:1234", grpc.WithInsecure()) 14 | if err != nil { 15 | log.Fatal(err) 16 | } 17 | defer conn.Close() 18 | 19 | client := pb.NewPubsubServiceClient(conn) 20 | 21 | _, err = client.Publish(context.Background(), &pb.String{Value: "golang: hello Go"}) 22 | if err != nil { 23 | log.Fatal(err) 24 | } 25 | _, err = client.Publish(context.Background(), &pb.String{Value: "docker: hello Docker"}) 26 | if err != nil { 27 | log.Fatal(err) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /examples/ch4.4/3/clientsub/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "io" 7 | "log" 8 | 9 | "google.golang.org/grpc" 10 | 11 | pb "ch4.4-3/pubsubservice" 12 | ) 13 | 14 | func main() { 15 | conn, err := grpc.Dial("localhost:1234", grpc.WithInsecure()) 16 | if err != nil { 17 | log.Fatal(err) 18 | } 19 | defer conn.Close() 20 | 21 | client := pb.NewPubsubServiceClient(conn) 22 | stream, err := client.Subscribe(context.Background(), &pb.String{Value: "golang:"}) 23 | if err != nil { 24 | log.Fatal(err) 25 | } 26 | 27 | for { 28 | reply, err := stream.Recv() 29 | if err != nil { 30 | if err == io.EOF { 31 | break 32 | } 33 | log.Fatal(err) 34 | } 35 | 36 | fmt.Println(reply.GetValue()) 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /examples/ch4.4/3/pubsubservice/pubsubservice.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package pubsubservice; 4 | 5 | message String { 6 | string value = 1; 7 | } 8 | 9 | service PubsubService { 10 | rpc Publish (String) returns (String); 11 | rpc Subscribe (String) returns (stream String); 12 | } 13 | 14 | //protoc --go_out=plugins=grpc:. pubsubservice.proto 15 | -------------------------------------------------------------------------------- /examples/ch4.4/basic/client/Makefile: -------------------------------------------------------------------------------- 1 | default: 2 | protoc --go_out=plugins=grpc:. hello.proto 3 | -------------------------------------------------------------------------------- /examples/ch4.4/basic/client/hello.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package main; 4 | 5 | message String { 6 | string value = 1; 7 | } 8 | 9 | service HelloService { 10 | rpc Hello (String) returns (String); 11 | 12 | rpc Channel (stream String) returns (stream String); 13 | } 14 | -------------------------------------------------------------------------------- /examples/ch4.4/grpc-pubsub/clientPub/clientPub.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "log" 6 | 7 | "google.golang.org/grpc" 8 | 9 | pb "gobook.examples/ch4-04-grpc/grpc-pubsub/pubsubservice" 10 | ) 11 | 12 | func main() { 13 | conn, err := grpc.Dial("localhost:1234", grpc.WithInsecure()) 14 | if err != nil { 15 | log.Fatal(err) 16 | } 17 | defer conn.Close() 18 | 19 | client := pb.NewPubsubServiceClient(conn) 20 | 21 | _, err = client.Publish(context.Background(), &pb.String{Value: "golang: hello Go"}) 22 | if err != nil { 23 | log.Fatal(err) 24 | } 25 | _, err = client.Publish(context.Background(), &pb.String{Value: "docker: hello Docker"}) 26 | if err != nil { 27 | log.Fatal(err) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /examples/ch4.4/grpc-pubsub/clientSub/clientSub.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "io" 7 | "log" 8 | 9 | "google.golang.org/grpc" 10 | 11 | pb "gobook.examples/ch4-04-grpc/grpc-pubsub/pubsubservice" 12 | ) 13 | 14 | func main() { 15 | conn, err := grpc.Dial("localhost:1234", grpc.WithInsecure()) 16 | if err != nil { 17 | log.Fatal(err) 18 | } 19 | defer conn.Close() 20 | 21 | client := pb.NewPubsubServiceClient(conn) 22 | stream, err := client.Subscribe(context.Background(), &pb.String{Value: "golang:"}) 23 | if err != nil { 24 | log.Fatal(err) 25 | } 26 | 27 | for { 28 | reply, err := stream.Recv() 29 | if err != nil { 30 | if err == io.EOF { 31 | break 32 | } 33 | log.Fatal(err) 34 | } 35 | 36 | fmt.Println(reply.GetValue()) 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /examples/ch4.4/grpc-pubsub/pubsubservice/pubsubservice.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package pubsubservice; 4 | 5 | message String { 6 | string value = 1; 7 | } 8 | 9 | service PubsubService { 10 | rpc Publish (String) returns (String); 11 | rpc Subscribe (String) returns (stream String); 12 | } 13 | 14 | //protoc --go_out=plugins=grpc:. pubsubservice.proto -------------------------------------------------------------------------------- /examples/ch4.5/on-web/Makefile: -------------------------------------------------------------------------------- 1 | 2 | run: 3 | @go build -o a.out && ./a.out 4 | -@rm ./a.out 5 | 6 | gen: 7 | protoc -I . --go_out=plugins=grpc:. helloworld.proto 8 | 9 | clean: 10 | -rm *.pb.go 11 | -------------------------------------------------------------------------------- /examples/ch4.5/on-web/helloworld.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package main; 4 | 5 | service Greeter { 6 | rpc SayHello (HelloRequest) returns (HelloReply); 7 | } 8 | 9 | message HelloRequest { 10 | string name = 1; 11 | } 12 | 13 | message HelloReply { 14 | string message = 1; 15 | } 16 | -------------------------------------------------------------------------------- /examples/ch4.5/on-web/tls-config/Makefile: -------------------------------------------------------------------------------- 1 | 2 | default: 3 | openssl genrsa -out server.key 2048 4 | openssl req -new -x509 -days 3650 \ 5 | -subj "/C=GB/L=China/O=gobook/CN=server.grpc.io" \ 6 | -key server.key -out server.crt 7 | 8 | clean: 9 | -rm *.key *.crt *.csr *.srl 10 | 11 | -------------------------------------------------------------------------------- /examples/ch4.5/on-web/tls-config/server.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDCjCCAfICCQD94/YEp09k1TANBgkqhkiG9w0BAQsFADBHMQswCQYDVQQGEwJH 3 | QjEOMAwGA1UEBwwFQ2hpbmExDzANBgNVBAoMBmdvYm9vazEXMBUGA1UEAwwOc2Vy 4 | dmVyLmdycGMuaW8wHhcNMTgwNzE0MTAzMTUyWhcNMjgwNzExMTAzMTUyWjBHMQsw 5 | CQYDVQQGEwJHQjEOMAwGA1UEBwwFQ2hpbmExDzANBgNVBAoMBmdvYm9vazEXMBUG 6 | A1UEAwwOc2VydmVyLmdycGMuaW8wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK 7 | AoIBAQCsE9wEkF46VQ62jwaS/udWdoB6VfTBFngYrtSLt2JEOV1DqSXVUSnKU6es 8 | xdBpRVWuIJFoE7Nl+9HA24qsBf/RvVr7V0xcbp0E4I8V05NldQrzAr3J4hti7gA7 9 | 720wADLdKfbwmikftM3UZHFNgy5dzZIj0EDA1HyANv41JRG/h9OVWM6g6ENLs5zL 10 | HNBKDvAJVg2q5iwfaDW5j1AmqmAXDkFqdq7W41PZA15P/NtY4vOLbq6lI0SXjqnW 11 | i1QyDalU8v6v1oSjMBIUkmm8HSRJ1KTul8BPEUu1k1Tos1GdUroGK9R2/gDz3pdA 12 | cqR0lcv2Wzt6RXroaqtliJosqHHtAgMBAAEwDQYJKoZIhvcNAQELBQADggEBADpA 13 | g+wrvJ5xlLWViXOfbluU1VZ4uRovg9mpJ7uJt5rKEJanNPbpKmgSfnztZulfg55j 14 | OsPQuoJafJGfor6tCx8RYqD1FQtevoqxPl5oY4+re9vCJTe0Tc9+V3OdCwZ0YhuZ 15 | UMTabh73Gl93a8RdAzTFQtEaAtBeuE7EjF16xeKKx+E5u4JO6srTbPuFMDC4z30h 16 | fpfSfscZS4DVRI2CuKv1XI1GHCzSmxFPe/keli7vb/+Bu+hVCBuFFbqbGXRD0BGX 17 | y8qIHD3GwI166L1RflgDgmgrQgXsvrvlixajdj/d5bT3kok8xM/pY4ufqJWNr4vA 18 | QxoCpEnWThyIQEU3aGI= 19 | -----END CERTIFICATE----- 20 | -------------------------------------------------------------------------------- /examples/ch4.5/panic-and-log/Makefile: -------------------------------------------------------------------------------- 1 | 2 | run: 3 | @go build -o a.out && ./a.out 4 | -@rm ./a.out 5 | 6 | gen: 7 | protoc -I . --go_out=plugins=grpc:. helloworld.proto 8 | 9 | clean: 10 | -rm *.pb.go 11 | -------------------------------------------------------------------------------- /examples/ch4.5/panic-and-log/helloworld.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package main; 4 | 5 | service Greeter { 6 | rpc SayHello (HelloRequest) returns (HelloReply); 7 | } 8 | 9 | message HelloRequest { 10 | string name = 1; 11 | } 12 | 13 | message HelloReply { 14 | string message = 1; 15 | } 16 | -------------------------------------------------------------------------------- /examples/ch4.5/rest-and-swagger/dummy.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/examples/ch4.5/rest-and-swagger/dummy.txt -------------------------------------------------------------------------------- /examples/ch4.5/tls/Makefile: -------------------------------------------------------------------------------- 1 | 2 | run: 3 | @go build -o a.out && ./a.out 4 | -@rm ./a.out 5 | 6 | gen: 7 | protoc -I . --go_out=plugins=grpc:. helloworld.proto 8 | 9 | clean: 10 | -rm *.pb.go 11 | -------------------------------------------------------------------------------- /examples/ch4.5/tls/helloworld.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package main; 4 | 5 | service Greeter { 6 | rpc SayHello (HelloRequest) returns (HelloReply); 7 | } 8 | 9 | message HelloRequest { 10 | string name = 1; 11 | } 12 | 13 | message HelloReply { 14 | string message = 1; 15 | } 16 | -------------------------------------------------------------------------------- /examples/ch4.5/tls/tls-config/Makefile: -------------------------------------------------------------------------------- 1 | 2 | default: 3 | # ca 4 | openssl genrsa -out ca.key 2048 5 | openssl req -new -x509 -days 3650 \ 6 | -subj "/C=GB/L=China/O=gobook/CN=github.com" \ 7 | -key ca.key -out ca.crt 8 | 9 | # server 10 | openssl genrsa \ 11 | -out server.key 2048 12 | openssl req -new \ 13 | -subj "/C=GB/L=China/O=server/CN=server.io" \ 14 | -key server.key \ 15 | -out server.csr 16 | openssl x509 -req -sha256 \ 17 | -CA ca.crt -CAkey ca.key -CAcreateserial -days 3650 \ 18 | -in server.csr \ 19 | -out server.crt 20 | 21 | # client 22 | openssl genrsa \ 23 | -out client.key 2048 24 | openssl req -new \ 25 | -subj "/C=GB/L=China/O=client/CN=client.io" \ 26 | -key client.key \ 27 | -out client.csr 28 | openssl x509 -req -sha256 \ 29 | -CA ca.crt -CAkey ca.key -CAcreateserial -days 3650 \ 30 | -in client.csr \ 31 | -out client.crt 32 | 33 | clean: 34 | -rm *.key *.crt *.csr *.srl 35 | 36 | -------------------------------------------------------------------------------- /examples/ch4.5/tls/tls-config/ca.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDAjCCAeoCCQCF2wMTBQwdFzANBgkqhkiG9w0BAQsFADBDMQswCQYDVQQGEwJH 3 | QjEOMAwGA1UEBwwFQ2hpbmExDzANBgNVBAoMBmdvYm9vazETMBEGA1UEAwwKZ2l0 4 | aHViLmNvbTAeFw0xODA3MTQwNjA4MThaFw0yODA3MTEwNjA4MThaMEMxCzAJBgNV 5 | BAYTAkdCMQ4wDAYDVQQHDAVDaGluYTEPMA0GA1UECgwGZ29ib29rMRMwEQYDVQQD 6 | DApnaXRodWIuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuy/H 7 | 36okEjS7rQvZ2ImfCFOsDqrr2AZB4UqDC84qukku82oa7BUkpZIpxZ4gWZoRRnWv 8 | YXqO+2wcP9lrfcaJeCJARh5iu8OMlPrLdlKFsgdw+R6rVxNVary9ZOj7OmyBSsue 9 | tJjb6v8UWlifKxseW9ame/m3bMg6WM69UxHtp4PDPBsImN9LiuGPMfyaQ8G02rxL 10 | mZk47v8mphcHBPtM91ozqqXtMrFc7l7+51J2Rrfx2n4zO1gJaOM5fpNoCejRlRxp 11 | lRlGJjg4wLhWJ5aKarJZeokNB2LAk3hEolFS2fkUr8bn1xq2Gcte8jFiFUCSyEvH 12 | pkjgB657obw1tXJwyQIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQCFe+APzr6QBC49 13 | t57zRGIc2ol/D6znnzBedOQn/WvaOHyQfdfD04jO6AcsOvBA0Kb4A3NWdBOT2jpN 14 | fkPhwFQxvuXmc6MQOo7Ud7IjPd4x6B8vjmUr3aNa5F/4A5JlR2mfkngSGIRhRjkR 15 | qb51s1K/jqJYVeikjexUB2YafeI71G12IkR6/3i1M+xuVt2H+vl3AMoR3iwfOltE 16 | 8UtvTJmnU0g4UjcfWNz1UwP7A4+VuARSuNVbmN+h4G8lDJBdqOVyZI4Xb/9ZZjx3 17 | Y9oyDXCAVvFY1o2RQUBjb/Z0s4tBfCj46S6ma5NG9aukW+BbP7U9VHr95rEQ9pqm 18 | Xd3DS3Nd 19 | -----END CERTIFICATE----- 20 | -------------------------------------------------------------------------------- /examples/ch4.5/tls/tls-config/ca.srl: -------------------------------------------------------------------------------- 1 | AC85DE90D9B5C67D 2 | -------------------------------------------------------------------------------- /examples/ch4.5/tls/tls-config/client.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDATCCAekCCQCshd6Q2bXGfTANBgkqhkiG9w0BAQsFADBDMQswCQYDVQQGEwJH 3 | QjEOMAwGA1UEBwwFQ2hpbmExDzANBgNVBAoMBmdvYm9vazETMBEGA1UEAwwKZ2l0 4 | aHViLmNvbTAeFw0xODA3MTQwNjA4MjJaFw0yODA3MTEwNjA4MjJaMEIxCzAJBgNV 5 | BAYTAkdCMQ4wDAYDVQQHDAVDaGluYTEPMA0GA1UECgwGY2xpZW50MRIwEAYDVQQD 6 | DAljbGllbnQuaW8wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCzQ8AA 7 | A1fLAnXbFS7GpJBz4kGSYlWODc3BorXlgCEUMi3BAEkfbdXryy1kvnQ70NCCPxN6 8 | Ixr/EAO5BhSEQz4tuIc4RfgXN3qK5Z3eVcR+qMUjixq5IuaNPxfo9u5xt+83rSpR 9 | Xxz5Vt84fn3RToB1Kvw1E/IwkIYrryzUosB6gWkBs2uUw7bPJhS4OazkpO/KKtJ8 10 | MnHD8JWSSDevoSDL/UNKpR4pM0c6vLOuxjzlWD7uAHamQV9t/95kLD40yTaedHNb 11 | PbA3ayVU3yrVoQfZQb/kNj1mmboemqcSQuRD7K7Qm/6Oul9mDxNWrevl5sF5yAgO 12 | dAI+8r3OSiblXXWvAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAFh1N4xNwnjHT8IG 13 | kj8aNf9LxXJ6fOaEHO//6Be7LG20/PbG1lr9TfkxlLhc3ywCUve9kDhIkAxd7NCM 14 | Tt/1363E3evN1owApmJgd5xLMkL0HUKkl8AuyIxwgzDyheVSWzbbVQw6vQpZbWrK 15 | 5qCohV41u/3fXQI4fwEg1Ry/oYrv9ky72HkBxPUBrfvLON0psfDtYtwycwOB8e/n 16 | smwTabWVCl8Ovr6oKBUpiv0q5NyHN2DATrkt+Q3Kgzeu9/7Lcnsf0u41eOY0f/0d 17 | /gc3xmrDQgDZZd0HwLOnQ/iDp99dD59OSPQWREnlSQSAqFWI+E0UffeAOZjpRsBL 18 | 6LsFM1g= 19 | -----END CERTIFICATE----- 20 | -------------------------------------------------------------------------------- /examples/ch4.5/tls/tls-config/client.csr: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE REQUEST----- 2 | MIIChzCCAW8CAQAwQjELMAkGA1UEBhMCR0IxDjAMBgNVBAcMBUNoaW5hMQ8wDQYD 3 | VQQKDAZjbGllbnQxEjAQBgNVBAMMCWNsaWVudC5pbzCCASIwDQYJKoZIhvcNAQEB 4 | BQADggEPADCCAQoCggEBALNDwAADV8sCddsVLsakkHPiQZJiVY4NzcGiteWAIRQy 5 | LcEASR9t1evLLWS+dDvQ0II/E3ojGv8QA7kGFIRDPi24hzhF+Bc3eorlnd5VxH6o 6 | xSOLGrki5o0/F+j27nG37zetKlFfHPlW3zh+fdFOgHUq/DUT8jCQhiuvLNSiwHqB 7 | aQGza5TDts8mFLg5rOSk78oq0nwyccPwlZJIN6+hIMv9Q0qlHikzRzq8s67GPOVY 8 | Pu4AdqZBX23/3mQsPjTJNp50c1s9sDdrJVTfKtWhB9lBv+Q2PWaZuh6apxJC5EPs 9 | rtCb/o66X2YPE1at6+XmwXnICA50Aj7yvc5KJuVdda8CAwEAAaAAMA0GCSqGSIb3 10 | DQEBCwUAA4IBAQA0QPsLKzSBaoHdod/ByiCqFfnDVxEoKFZrM3eZA74E9SGlpVfE 11 | Hzk082u3bN+X+Jme2e1+mob8RvRoGzqprAtz2W2EMryhSJkwVpUGfio7DXZy1PGK 12 | RzyqEbNa3OrlphHihGKHqs+Y1MiVsXZQJO2M8zgUHiLIdbjODj/SLvK5xJlfGNZz 13 | Ezy6mjAIYlXszGOD1VfI3h4LwFCmDOc2YROtkvB3f0xhs7KrO/6ywupMO17M3Tbo 14 | HSU5Mb+sLMOt0JfqYohuMnFy8ck5ABximrCULa5yGD+Xyjr/Absd4Ou0WnV5HaY8 15 | e/1ylsnQ2ll6lJ3VKOaGD+oJcAV53pcNZfnK 16 | -----END CERTIFICATE REQUEST----- 17 | -------------------------------------------------------------------------------- /examples/ch4.5/tls/tls-config/server.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDATCCAekCCQCshd6Q2bXGfDANBgkqhkiG9w0BAQsFADBDMQswCQYDVQQGEwJH 3 | QjEOMAwGA1UEBwwFQ2hpbmExDzANBgNVBAoMBmdvYm9vazETMBEGA1UEAwwKZ2l0 4 | aHViLmNvbTAeFw0xODA3MTQwNjA4MjFaFw0yODA3MTEwNjA4MjFaMEIxCzAJBgNV 5 | BAYTAkdCMQ4wDAYDVQQHDAVDaGluYTEPMA0GA1UECgwGc2VydmVyMRIwEAYDVQQD 6 | DAlzZXJ2ZXIuaW8wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDJ75GO 7 | flZqoTWU8ugLd+GRuiXN1cgeN8vIWBC57jZuCMchURrd/ACufK3U/0ZuEExvDKxw 8 | CVhzH3fJt+uZ5d18fHGFKTIP2YFjAQKeUmOWs8wUAg54Fyr/Rlx6tnLGVcgvrSsR 9 | IswEq32/cZY73My93jayKZx0xBKHSof7Rw6rfhJgukBnFjfXoRKIJh7cZCgn/wpA 10 | KPPUu8LvbbBhkHmDSQhjM4N/KinMuh+qp/d+3MNcaf0r5zJpN9IrObX4R6Vbh+W4 11 | 3DR26DdlbrlJG+P8afp3v02R46Clyj9udq9YBa+cS4UzPHec1Emfc2NP0nU/yo5/ 12 | mrnhyn8bRV/rbHZZAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAHJ9IXreSURKe0nT 13 | AejfEV2qK0vqCtEUlvmGY3JrSVtig/HG9YPO9bfdBIg1QevTnIBBXrQIfNQ0jXOY 14 | D4Jw6laAezhL/J1LNuKz8SMQ4dMPkru/bRfkT/98tb/A80rpq177grTtKuxvI3FE 15 | 0k6moFQFpjQnna5T9n7uT+nkv0tkadXHKMaj2ngNUr4US4IDTDk3h9tpazj74pzl 16 | eWWUF+sYgNuzHT9kH4wxsIXtm5Uyj1FWf2cO8VKhZs1aHHm7etKsf7yncITfne/q 17 | XAtfm4cdd8BRc0QdvYV3DFJPyloyyP4OM3TCGTrHe7/UAPL1c1+eNB0kG5zGY/o4 18 | gT0GhPA= 19 | -----END CERTIFICATE----- 20 | -------------------------------------------------------------------------------- /examples/ch4.5/tls/tls-config/server.csr: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE REQUEST----- 2 | MIIChzCCAW8CAQAwQjELMAkGA1UEBhMCR0IxDjAMBgNVBAcMBUNoaW5hMQ8wDQYD 3 | VQQKDAZzZXJ2ZXIxEjAQBgNVBAMMCXNlcnZlci5pbzCCASIwDQYJKoZIhvcNAQEB 4 | BQADggEPADCCAQoCggEBAMnvkY5+VmqhNZTy6At34ZG6Jc3VyB43y8hYELnuNm4I 5 | xyFRGt38AK58rdT/Rm4QTG8MrHAJWHMfd8m365nl3Xx8cYUpMg/ZgWMBAp5SY5az 6 | zBQCDngXKv9GXHq2csZVyC+tKxEizASrfb9xljvczL3eNrIpnHTEEodKh/tHDqt+ 7 | EmC6QGcWN9ehEogmHtxkKCf/CkAo89S7wu9tsGGQeYNJCGMzg38qKcy6H6qn937c 8 | w1xp/SvnMmk30is5tfhHpVuH5bjcNHboN2VuuUkb4/xp+ne/TZHjoKXKP252r1gF 9 | r5xLhTM8d5zUSZ9zY0/SdT/Kjn+aueHKfxtFX+tsdlkCAwEAAaAAMA0GCSqGSIb3 10 | DQEBCwUAA4IBAQBnpfRE5zrDNLnLAA4DWGlzdnyhFiX4h9eDhiRXeodLLEYSg8jV 11 | x5gLTWE3wq3S60AGw56p/lPD0Q6BWBk1zxDFfpa4Yj+GQWqK+fC3ek9FqmL6iVmM 12 | Sbtdw+4mVmksRR+V4WU6ixqIjGhw62TS00kMUTuudNQvqZBCm/rYviicCgaQbe0V 13 | 8NgjEkbMPsdc9hP+3luEqjOb/6+pbYEjj2zmz7avJHyNYLcmnC+014l+/X5wY7Aw 14 | albenvhePdta6JR0K0k16BZnHNpoMHc9pdYGea80WQzk7sHK6aXv81biZt7FlzO4 15 | sLNYFeaQrytLPoUToC2YkonRKU+2DZfa6ZSn 16 | -----END CERTIFICATE REQUEST----- 17 | -------------------------------------------------------------------------------- /examples/ch4.5/tok/Makefile: -------------------------------------------------------------------------------- 1 | 2 | run: 3 | @go build -o a.out && ./a.out 4 | -@rm ./a.out 5 | 6 | gen: 7 | protoc -I . --go_out=plugins=grpc:. helloworld.proto 8 | 9 | clean: 10 | -rm *.pb.go 11 | -------------------------------------------------------------------------------- /examples/ch4.5/tok/helloworld.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package main; 4 | 5 | service Greeter { 6 | rpc SayHello (HelloRequest) returns (HelloReply); 7 | } 8 | 9 | message HelloRequest { 10 | string name = 1; 11 | } 12 | 13 | message HelloReply { 14 | string message = 1; 15 | } 16 | -------------------------------------------------------------------------------- /examples/ch4.6/pb2-default-value/Makefile: -------------------------------------------------------------------------------- 1 | 2 | run: 3 | @go build -o a.out && ./a.out 4 | -@rm ./a.out 5 | 6 | gen: 7 | protoc -I . --go_out=plugins=grpc:. helloworld.proto 8 | 9 | clean: 10 | -rm *.pb.go 11 | -------------------------------------------------------------------------------- /examples/ch4.6/pb2-default-value/helloworld.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package main; 4 | 5 | import "google/protobuf/descriptor.proto"; 6 | 7 | extend google.protobuf.FieldOptions { 8 | string default_string = 50000; 9 | int32 default_int = 50001; 10 | } 11 | 12 | message Message { 13 | string name = 1 [(default_string) = "gopher"]; 14 | int32 age = 2[(default_int) = 10]; 15 | } 16 | -------------------------------------------------------------------------------- /examples/ch4.6/rest/Makefile: -------------------------------------------------------------------------------- 1 | 2 | run: 3 | @go build -o a.out && ./a.out 4 | -@rm ./a.out 5 | 6 | gen: 7 | protoc \ 8 | -I=. -I=../../../github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis \ 9 | --go_out=plugins=grpc:. \ 10 | helloworld.proto 11 | protoc \ 12 | -I=. -I=../../../github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis \ 13 | --grpc-gateway_out=. \ 14 | helloworld.proto 15 | protoc \ 16 | -I=. -I=../../../github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis \ 17 | --swagger_out=. \ 18 | helloworld.proto 19 | 20 | clean: 21 | -rm *.pb.go 22 | -------------------------------------------------------------------------------- /examples/ch4.6/rest/helloworld.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package main; 4 | 5 | import "google/api/annotations.proto"; 6 | 7 | message StringMessage { 8 | string value = 1; 9 | } 10 | 11 | service RestService { 12 | rpc Get(StringMessage) returns (StringMessage) { 13 | option (google.api.http) = { 14 | get: "/get/{value}" 15 | }; 16 | } 17 | rpc Post(StringMessage) returns (StringMessage) { 18 | option (google.api.http) = { 19 | post: "/post" 20 | body: "*" 21 | }; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /examples/ch4.6/validators/Makefile: -------------------------------------------------------------------------------- 1 | 2 | run: 3 | @go build -o a.out && ./a.out 4 | -@rm ./a.out 5 | 6 | aa: 7 | cd ../../.. && pwd 8 | 9 | gen: 10 | protoc -I=. -I=../../.. --go_out=plugins=grpc:. helloworld.proto 11 | protoc -I=. -I=../../.. --govalidators_out=. helloworld.proto 12 | 13 | clean: 14 | -rm *.pb.go 15 | -------------------------------------------------------------------------------- /examples/ch4.6/validators/helloworld.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package main; 4 | 5 | import "github.com/mwitkow/go-proto-validators/validator.proto"; 6 | 7 | message Message { 8 | string important_string = 1 [(validator.field) = {regex: "^[a-z]{2,5}$"}]; 9 | int32 age = 2 [(validator.field) = {int_gt: 0, int_lt: 100}]; 10 | } 11 | -------------------------------------------------------------------------------- /examples/ch4.6/validators/helloworld.validator.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-gogo. DO NOT EDIT. 2 | // source: helloworld.proto 3 | 4 | /* 5 | Package main is a generated protocol buffer package. 6 | 7 | It is generated from these files: 8 | helloworld.proto 9 | 10 | It has these top-level messages: 11 | Message 12 | */ 13 | package main 14 | 15 | import regexp "regexp" 16 | import fmt "fmt" 17 | import go_proto_validators "github.com/mwitkow/go-proto-validators" 18 | import proto "github.com/golang/protobuf/proto" 19 | import math "math" 20 | import _ "github.com/mwitkow/go-proto-validators" 21 | 22 | // Reference imports to suppress errors if they are not otherwise used. 23 | var _ = proto.Marshal 24 | var _ = fmt.Errorf 25 | var _ = math.Inf 26 | 27 | var _regex_Message_ImportantString = regexp.MustCompile("^[a-z]{2,5}$") 28 | 29 | func (this *Message) Validate() error { 30 | if !_regex_Message_ImportantString.MatchString(this.ImportantString) { 31 | return go_proto_validators.FieldError("ImportantString", fmt.Errorf(`value '%v' must be a string conforming to regex "^[a-z]{2,5}$"`, this.ImportantString)) 32 | } 33 | if !(this.Age > 0) { 34 | return go_proto_validators.FieldError("Age", fmt.Errorf(`value '%v' must be greater than '0'`, this.Age)) 35 | } 36 | if !(this.Age < 100) { 37 | return go_proto_validators.FieldError("Age", fmt.Errorf(`value '%v' must be less than '100'`, this.Age)) 38 | } 39 | return nil 40 | } 41 | -------------------------------------------------------------------------------- /examples/ch4.7/http-router/dummy.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/examples/ch4.7/http-router/dummy.txt -------------------------------------------------------------------------------- /examples/ch4.7/pb-option/Makefile: -------------------------------------------------------------------------------- 1 | 2 | run: 3 | @go build -o a.out && ./a.out 4 | -@rm ./a.out 5 | 6 | gen: 7 | protoc -I . --go_out=plugins=grpc:. helloworld.proto 8 | 9 | clean: 10 | -rm *.pb.go 11 | -------------------------------------------------------------------------------- /examples/ch4.7/pb-option/dummy.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/examples/ch4.7/pb-option/dummy.txt -------------------------------------------------------------------------------- /examples/ch4.7/pb-option/helloworld.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto2"; 2 | 3 | package main; 4 | 5 | import "google/protobuf/descriptor.proto"; 6 | 7 | extend google.protobuf.FileOptions { 8 | optional String file_option = 50000; 9 | } 10 | 11 | extend google.protobuf.MessageOptions { 12 | optional String message_option = 50000; 13 | } 14 | extend google.protobuf.FieldOptions { 15 | optional String filed_option = 50000; 16 | } 17 | 18 | extend google.protobuf.ServiceOptions { 19 | optional String service_option = 50000; 20 | } 21 | extend google.protobuf.MethodOptions { 22 | optional String method_option = 50000; 23 | } 24 | 25 | option (file_option) = { 26 | value: "this is a file option" 27 | }; 28 | 29 | message Message { 30 | option (message_option) = { 31 | value: "message option" 32 | }; 33 | 34 | optional string name = 1 [ 35 | (filed_option) = { 36 | value: "" 37 | } 38 | ]; 39 | } 40 | 41 | service HelloService { 42 | option (service_option) = { 43 | value: "message option" 44 | }; 45 | 46 | rpc Hello(String) returns(String) { 47 | option (method_option) = { 48 | value: "" 49 | }; 50 | } 51 | } 52 | 53 | message String { 54 | optional string value = 1; 55 | } 56 | -------------------------------------------------------------------------------- /examples/ch4.7/pb-web-frameswork/dummy.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/examples/ch4.7/pb-web-frameswork/dummy.txt -------------------------------------------------------------------------------- /examples/ch4.7/plugin-framework/dummy.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/examples/ch4.7/plugin-framework/dummy.txt -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | // Copyright 2018 . All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | module chai2010.cn/gobook 6 | 7 | require github.com/chai2010/advanced-go-programming-book v0.0.0-20181214135029-bcf560505d53 // indirect 8 | 9 | go 1.13 10 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/chai2010/advanced-go-programming-book v0.0.0-20181214135029-bcf560505d53 h1:aq3N3UiILJGY2ACWiJ6uEktcOT3NK0rikqLN3yzh12k= 2 | github.com/chai2010/advanced-go-programming-book v0.0.0-20181214135029-bcf560505d53/go.mod h1:V6DFKY/3DuWA1gVR1lM6rnqPfdKquvbsXb1ei9MmipA= 3 | -------------------------------------------------------------------------------- /images/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright 2017 . All rights reserved. 2 | # Use of this source code is governed by a Apache 3 | # license that can be found in the LICENSE file. 4 | 5 | UML_FILES=$(wildcard ./*.plantuml) 6 | UML_SVG_FILES=$(patsubst %.plantuml,%.uml.svg,$(UML_FILES)) 7 | UML_PNG_FILES=$(patsubst %.plantuml,%.uml.png,$(UML_FILES)) 8 | 9 | DOT_FILES=$(wildcard ./*.dot) 10 | DOT_PNG_FILES=$(patsubst %.dot,%.dot.png,$(DOT_FILES)) 11 | 12 | DITAA_FILES=$(wildcard ./*.ditaa.txt) 13 | DITAA_PNG_FILES=$(patsubst %.ditaa.txt,%.ditaa.png,$(DITAA_FILES)) 14 | 15 | default: $(UML_PNG_FILES) $(DOT_PNG_FILES) $(DITAA_PNG_FILES) 16 | @echo "ok" 17 | 18 | logo: 19 | convert logo-2018-01.png -resize 300x65 logo.png 20 | @echo "ok" 21 | 22 | clean: 23 | -rm *.dot.png 24 | -rm *.uml.png 25 | -rm *.uml.svg 26 | 27 | %.uml.svg: %.plantuml 28 | cat $< | docker run --rm -i chai2010/ibox:plantuml > $@ 29 | 30 | %.uml.png: %.plantuml 31 | cat $< | docker run --rm -i chai2010/ibox:plantuml -tpng > $@ 32 | 33 | %.dot.png: %.dot 34 | dot -Tpng -o $@ $< 35 | 36 | %.ditaa.png: %.ditaa.txt 37 | docker run --rm -it -v `pwd`:/root chai2010/ibox:ditaa $< $@ 38 | -------------------------------------------------------------------------------- /images/appendix-c-chai2010.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/appendix-c-chai2010.jpg -------------------------------------------------------------------------------- /images/by-nc-sa-4.0-88x31.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/by-nc-sa-4.0-88x31.png -------------------------------------------------------------------------------- /images/ch1-1-go-family-tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/ch1-1-go-family-tree.png -------------------------------------------------------------------------------- /images/ch1-10-slice-1.ditaa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/ch1-10-slice-1.ditaa.png -------------------------------------------------------------------------------- /images/ch1-10-slice-1.ditaa.txt: -------------------------------------------------------------------------------- 1 | +-------+-------+-------+ 2 | | ptr | len:5 | cap:5 | []int 3 | +-------+-------+-------+ 4 | | | | 5 | +-=-+ | | 6 | | | | 7 | |<-=--------+-------+------------------>| 8 | v 9 | +-------+-------+-------+-------+-------+ 10 | | 2 | 3 | 5 | 7 | 11 | [5]int 11 | +-------+-------+-------+-------+-------+ 12 | ^ 13 | |<--------=---------+---------->| 14 | |<--------=+--->| | 15 | | | | 16 | +-=-+ | | 17 | | | | 18 | +---+---+-------+-------+ 19 | | ptr | len:2 | cap:4 | []int 20 | +-------+-------+-------+ 21 | -------------------------------------------------------------------------------- /images/ch1-11-init.ditaa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/ch1-11-init.ditaa.png -------------------------------------------------------------------------------- /images/ch1-12-init.ditaa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/ch1-12-init.ditaa.png -------------------------------------------------------------------------------- /images/ch1-13-prime-sieve.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/ch1-13-prime-sieve.png -------------------------------------------------------------------------------- /images/ch1-2-go-log4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/ch1-2-go-log4.png -------------------------------------------------------------------------------- /images/ch1-3-go-history.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/ch1-3-go-history.png -------------------------------------------------------------------------------- /images/ch1-4-go-history.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/ch1-4-go-history.png -------------------------------------------------------------------------------- /images/ch1-5-prime-sieve.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/ch1-5-prime-sieve.png -------------------------------------------------------------------------------- /images/ch1-6-alef.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/ch1-6-alef.png -------------------------------------------------------------------------------- /images/ch1-7-array-4int.ditaa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/ch1-7-array-4int.ditaa.png -------------------------------------------------------------------------------- /images/ch1-7-array-4int.ditaa.txt: -------------------------------------------------------------------------------- 1 | +---+---+---+---+ 2 | | 2 | 3 | 5 | 7 | 3 | +---+---+---+---+ 4 | -------------------------------------------------------------------------------- /images/ch1-8-string-1.ditaa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/ch1-8-string-1.ditaa.png -------------------------------------------------------------------------------- /images/ch1-8-string-1.ditaa.txt: -------------------------------------------------------------------------------- 1 | hello, world 2 | +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+ 3 | | ... | h | e | l | l | o | , | | w | o | r | l | d | ... | 4 | +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+ 5 | ^ ^ 6 | | | 7 | +-----------=-+ : 8 | | | | 9 | +-----+---+ +---+----+ +---+----+ 10 | | data | | data | | data | 11 | +---------+ +--------+ +--------+ 12 | | len: 12 | | len: 5 | | len: 5 | 13 | +---------+ +--------+ +--------+ 14 | hello, world hello world 15 | -------------------------------------------------------------------------------- /images/ch1-9-string-2.ditaa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/ch1-9-string-2.ditaa.png -------------------------------------------------------------------------------- /images/ch1-9-string-2.ditaa.txt: -------------------------------------------------------------------------------- 1 | +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+ 2 | | ... | h | e | l | l | o | , | | E4 | B8 | 96 | E7 | 95 | 8C | ... | 3 | +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+ 4 | 5 | |<-------=- UTF8 Encoding -=-------->| 6 | -------------------------------------------------------------------------------- /images/ch2-1-x-ptr-to-y-ptr.plantuml: -------------------------------------------------------------------------------- 1 | ' Copyright 2017 . All rights reserved. 2 | ' Use of this source code is governed by a Apache 3 | ' license that can be found in the LICENSE file. 4 | 5 | @startuml 6 | 7 | title *X <=> *Y 8 | 9 | participant "~*X" as x_ptr 10 | participant unsafe.Pointer as unsafe_Pointer 11 | participant "~*Y" as y_ptr 12 | 13 | == *X => *Y == 14 | 15 | x_ptr -> unsafe_Pointer: ~*X to unsafe.Pointer 16 | unsafe_Pointer -> y_ptr: unsafe.Pointer to *Y 17 | 18 | == *Y => *X == 19 | 20 | y_ptr -> unsafe_Pointer: ~*Y to unsafe.Pointer 21 | unsafe_Pointer -> x_ptr: unsafe.Pointer to *X 22 | 23 | @enduml 24 | -------------------------------------------------------------------------------- /images/ch2-1-x-ptr-to-y-ptr.uml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/ch2-1-x-ptr-to-y-ptr.uml.png -------------------------------------------------------------------------------- /images/ch2-2-int32-to-char-ptr.plantuml: -------------------------------------------------------------------------------- 1 | ' Copyright 2017 . All rights reserved. 2 | ' Use of this source code is governed by a Apache 3 | ' license that can be found in the LICENSE file. 4 | 5 | @startuml 6 | 7 | title int32 <=> *C.char 8 | 9 | participant int32 10 | participant uintptr 11 | participant unsafe.Pointer as unsafe_Pointer 12 | participant "~*C.char" as c_char_ptr 13 | 14 | == Go == 15 | 16 | int32 -> uintptr: int32 to uintptr 17 | uintptr -> unsafe_Pointer: uintptr to unsafe.Pointer 18 | 19 | == CGO == 20 | 21 | unsafe_Pointer -> c_char_ptr: unsafe.Pointer to *C.char 22 | c_char_ptr -> unsafe_Pointer: ~*C.char to unsafe.Pointer 23 | 24 | == Go == 25 | 26 | unsafe_Pointer -> uintptr: unsafe.Pointer to uintptr 27 | uintptr -> int32: uintptr to int32 28 | 29 | @enduml 30 | -------------------------------------------------------------------------------- /images/ch2-2-int32-to-char-ptr.uml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/ch2-2-int32-to-char-ptr.uml.png -------------------------------------------------------------------------------- /images/ch2-3-x-slice-to-y-slice.plantuml: -------------------------------------------------------------------------------- 1 | ' Copyright 2017 . All rights reserved. 2 | ' Use of this source code is governed by a Apache 3 | ' license that can be found in the LICENSE file. 4 | 5 | 6 | 'var p []X 7 | 'var q []Y // q = p 8 | 9 | 'pHdr := (*reflect.SliceHeader)(unsafe.Pointer(&p)) 10 | 'qHdr := (*reflect.SliceHeader)(unsafe.Pointer(&q)) 11 | 12 | 'pHdr.Data = qHdr.Data 13 | 'pHdr.Len = qHdr.Len * unsafe.Sizeof(q[0]) / unsafe.Sizeof(p[0]) 14 | 'pHdr.Cap = qHdr.Cap * unsafe.Sizeof(q[0]) / unsafe.Sizeof(p[0]) 15 | 16 | 17 | @startuml 18 | 19 | title []X <=> []Y 20 | 21 | participant "var x []X\nvar y []Y" as slice 22 | participant "var px *SliceHeader\nvar py *SliceHeader" as slice_header 23 | 24 | == []X and []Y to *reflect.SliceHeader == 25 | 26 | slice -> slice_header: px := (*reflect.SliceHeader)(unsafe.Pointer(&x))\npy := (*reflect.SliceHeader)(unsafe.Pointer(&y)) 27 | 28 | == copy *px to *py == 29 | 30 | slice_header -> slice_header: ~*py = *px 31 | 32 | == y changed by *py == 33 | 34 | slice -> slice: y = x 35 | 36 | @enduml 37 | -------------------------------------------------------------------------------- /images/ch2-3-x-slice-to-y-slice.uml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/ch2-3-x-slice-to-y-slice.uml.png -------------------------------------------------------------------------------- /images/ch2-4-cgo-generated-files.dot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/ch2-4-cgo-generated-files.dot.png -------------------------------------------------------------------------------- /images/ch2-5-call-c-sum-v1.plantuml: -------------------------------------------------------------------------------- 1 | ' Copyright 2017 . All rights reserved. 2 | ' Use of this source code is governed by a Apache 3 | ' license that can be found in the LICENSE file. 4 | 5 | @startuml 6 | 7 | title C.sum(2, 3) 8 | 9 | |main.go| 10 | :func main() { 11 | C.sum(2, 3)) 12 | }; 13 | 14 | |#AntiqueWhite|main.cgo1.go| 15 | :func main() { 16 | _Cfunc_sum(2, 3)) 17 | }; 18 | 19 | |#AntiqueWhite|_cgo_types.go| 20 | :func _Cfunc_sum(2, 3) double { 21 | _cgo_runtime_cgocall(...) 22 | return 23 | }; 24 | 25 | |runtime.cgocall| 26 | :_cgo_runtime_cgocall(...); 27 | 28 | fork 29 | 30 | |#AntiqueWhite|main.cgo2.c| 31 | : double _cgo_xxx_Cfunc_sum(2, 3) { 32 | return sum(2, 3) 33 | }; 34 | 35 | |#AntiqueWhite|main.cgo2.c| 36 | : int sum(int a, int b) { 37 | return a+b 38 | }; 39 | 40 | endfork 41 | 42 | |runtime.cgocall| 43 | :_cgo_runtime_cgocall(...); 44 | 45 | |main.go| 46 | stop 47 | 48 | @enduml 49 | -------------------------------------------------------------------------------- /images/ch2-5-call-c-sum-v1.uml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/ch2-5-call-c-sum-v1.uml.png -------------------------------------------------------------------------------- /images/ch2-6-call-c-sum-v2.plantuml: -------------------------------------------------------------------------------- 1 | ' Copyright 2017 . All rights reserved. 2 | ' Use of this source code is governed by a Apache 3 | ' license that can be found in the LICENSE file. 4 | 5 | @startuml 6 | 7 | title c call go func 8 | 9 | |_testmain.c| 10 | :int main() { 11 | extern int sum(int a, int b) 12 | sum(1, 2) 13 | return 0 14 | }; 15 | -[#green,dashed]-> 16 | 17 | fork 18 | 19 | |#AntiqueWhite|_cgo_export.c| 20 | :int sum(int p0, int p1) { 21 | struct { int p0, p1, r0; } a 22 | _cgo_ctxt = _cgo_wait_runtime_init_done() 23 | crosscall2(_cgoexp_xxx_sum, &a, 16, _cgo_ctxt) 24 | _cgo_release_context(_cgo_ctxt) 25 | return a.r0 26 | }; 27 | 28 | |runtime/cgo/*.asm| 29 | :TEXT crosscall2(SB),NOSPLIT,$0; 30 | 31 | fork 32 | 33 | |#AntiqueWhite|_cgo_types.go| 34 | :func _cgoexp_xxx_sum(a unsafe.Pointer, n int32, ctxt uintptr) { 35 | fn := _cgoexpwrap_xxx_sum 36 | _cgo_runtime_cgocallback( 37 | _cgoexpwrap_xxx_sum, 38 | ... 39 | ) 40 | }; 41 | 42 | |#AntiqueWhite|_cgo_types.go| 43 | :func _cgoexpwrap_xxx_sum(p0, p1) r0 { 44 | return sum(p0, p1) 45 | }; 46 | 47 | |main.go| 48 | ://export sum 49 | func sum(a, b C.int) C.int { 50 | return a + b 51 | }; 52 | 53 | endfork 54 | 55 | |runtime/cgo/*.asm| 56 | :TEXT crosscall2(SB),NOSPLIT,$0; 57 | 58 | endfork 59 | 60 | |_testmain.c| 61 | stop 62 | 63 | @enduml 64 | -------------------------------------------------------------------------------- /images/ch2-6-call-c-sum-v2.uml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/ch2-6-call-c-sum-v2.uml.png -------------------------------------------------------------------------------- /images/ch3-1-arch-hsm-zero.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/ch3-1-arch-hsm-zero.jpg -------------------------------------------------------------------------------- /images/ch3-10-func-arg-01.ditaa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/ch3-10-func-arg-01.ditaa.png -------------------------------------------------------------------------------- /images/ch3-11-func-local-var-01.ditaa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/ch3-11-func-local-var-01.ditaa.png -------------------------------------------------------------------------------- /images/ch3-12-func-call-frame-01.ditaa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/ch3-12-func-call-frame-01.ditaa.png -------------------------------------------------------------------------------- /images/ch3-13-func-stack-frame-layout-01.ditaa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/ch3-13-func-stack-frame-layout-01.ditaa.png -------------------------------------------------------------------------------- /images/ch3-2-arch-amd64-01.ditaa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/ch3-2-arch-amd64-01.ditaa.png -------------------------------------------------------------------------------- /images/ch3-3-arch-amd64-02.ditaa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/ch3-3-arch-amd64-02.ditaa.png -------------------------------------------------------------------------------- /images/ch3-4-pkg-var-decl-01.ditaa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/ch3-4-pkg-var-decl-01.ditaa.png -------------------------------------------------------------------------------- /images/ch3-5-ieee754.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/ch3-5-ieee754.jpg -------------------------------------------------------------------------------- /images/ch3-6-pkg-var-decl-02.ditaa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/ch3-6-pkg-var-decl-02.ditaa.png -------------------------------------------------------------------------------- /images/ch3-7-pkg-var-decl-03.ditaa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/ch3-7-pkg-var-decl-03.ditaa.png -------------------------------------------------------------------------------- /images/ch3-8-func-decl-01.ditaa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/ch3-8-func-decl-01.ditaa.png -------------------------------------------------------------------------------- /images/ch3-9-func-decl-02.ditaa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/ch3-9-func-decl-02.ditaa.png -------------------------------------------------------------------------------- /images/ch4-1-grpc-go-stack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/ch4-1-grpc-go-stack.png -------------------------------------------------------------------------------- /images/ch4-2-grpc-gateway.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/ch4-2-grpc-gateway.png -------------------------------------------------------------------------------- /images/ch5-online-group.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/ch5-online-group.png -------------------------------------------------------------------------------- /images/ch5-set-time-line.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/ch5-set-time-line.png -------------------------------------------------------------------------------- /images/ch5-set-time-line_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/ch5-set-time-line_2.png -------------------------------------------------------------------------------- /images/ch5-token-bucket.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/ch5-token-bucket.png -------------------------------------------------------------------------------- /images/ch6-02-radix-get-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/ch6-02-radix-get-1.png -------------------------------------------------------------------------------- /images/ch6-02-radix-get-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/ch6-02-radix-get-2.png -------------------------------------------------------------------------------- /images/ch6-02-radix-get-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/ch6-02-radix-get-3.png -------------------------------------------------------------------------------- /images/ch6-02-radix-get-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/ch6-02-radix-get-4.png -------------------------------------------------------------------------------- /images/ch6-02-radix-put.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/ch6-02-radix-put.png -------------------------------------------------------------------------------- /images/ch6-02-radix.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/ch6-02-radix.png -------------------------------------------------------------------------------- /images/ch6-02-trie.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/ch6-02-trie.png -------------------------------------------------------------------------------- /images/ch6-03-gin_contrib.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/ch6-03-gin_contrib.png -------------------------------------------------------------------------------- /images/ch6-03-middleware_flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/ch6-03-middleware_flow.png -------------------------------------------------------------------------------- /images/ch6-04-validate-struct-tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/ch6-04-validate-struct-tree.png -------------------------------------------------------------------------------- /images/ch6-04-validate.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/ch6-04-validate.jpg -------------------------------------------------------------------------------- /images/ch6-06-leaky-bucket.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/ch6-06-leaky-bucket.jpg -------------------------------------------------------------------------------- /images/ch6-08-code-gen-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/ch6-08-code-gen-2.png -------------------------------------------------------------------------------- /images/ch6-08-code-gen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/ch6-08-code-gen.png -------------------------------------------------------------------------------- /images/ch6-08-control-flow-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/ch6-08-control-flow-2.png -------------------------------------------------------------------------------- /images/ch6-08-control-flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/ch6-08-control-flow.png -------------------------------------------------------------------------------- /images/ch6-08-controller-logic-dao.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/ch6-08-controller-logic-dao.png -------------------------------------------------------------------------------- /images/ch6-08-frontend-backend.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/ch6-08-frontend-backend.png -------------------------------------------------------------------------------- /images/ch6-08-plugin-arch.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/ch6-08-plugin-arch.jpg -------------------------------------------------------------------------------- /images/ch6-09-nats-protocol-pub.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/ch6-09-nats-protocol-pub.png -------------------------------------------------------------------------------- /images/ch6-09-nats-protocol-sub.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/ch6-09-nats-protocol-sub.png -------------------------------------------------------------------------------- /images/ch6-ast-dsl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/ch6-ast-dsl.png -------------------------------------------------------------------------------- /images/ch6-binary_tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/ch6-binary_tree.png -------------------------------------------------------------------------------- /images/ch6-binlog-sync.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/ch6-binlog-sync.png -------------------------------------------------------------------------------- /images/ch6-controller-logic-dao-storage.plantuml: -------------------------------------------------------------------------------- 1 | ' Copyright 2018 . All rights reserved. 2 | ' Use of this source code is governed by a Apache 3 | ' license that can be found in the LICENSE file. 4 | 5 | @startuml controller-logic-dao 6 | scale 1366*768 7 | 8 | 9 | activate Controller 10 | Controller -> Controller: validate input 11 | 12 | Controller -> Logic : build struct needed by logic, call function in logic 13 | activate Logic 14 | Logic -> Logic: logic check, use design patterns to work 15 | Logic -> Dao: call save order func 16 | activate Dao 17 | Dao -> Storage: save order 18 | Storage -> Dao: save order result 19 | Dao -> Logic: return save result 20 | deactivate Dao 21 | Logic -> Controller: return result 22 | deactivate Logic 23 | 24 | deactivate Controller 25 | @enduml -------------------------------------------------------------------------------- /images/ch6-controller-logic-dao-storage.uml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/ch6-controller-logic-dao-storage.uml.png -------------------------------------------------------------------------------- /images/ch6-data-dist1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/ch6-data-dist1.png -------------------------------------------------------------------------------- /images/ch6-data-dist2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/ch6-data-dist2.png -------------------------------------------------------------------------------- /images/ch6-dist-crawler.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/ch6-dist-crawler.png -------------------------------------------------------------------------------- /images/ch6-four-branch-tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/ch6-four-branch-tree.png -------------------------------------------------------------------------------- /images/ch6-interface-impl.plantuml: -------------------------------------------------------------------------------- 1 | @startuml interface-impl 2 | 3 | interface OrderCreator 4 | 5 | OrderCreator <|-- O2OOrderCreator 6 | OrderCreator <|-- B2BOrderCreator 7 | 8 | interface OrderCreator { 9 | ValidateDistrict() 10 | ValidateVIPProduct() 11 | GetUserInfo() 12 | GetProductDesc() 13 | DecrementStorage() 14 | CreateOrderSnapshot() 15 | } 16 | 17 | class O2OOrderCreator { 18 | ValidateDistrict() 19 | ValidateVIPProduct() 20 | GetUserInfo() 21 | GetProductDesc() 22 | DecrementStorage() 23 | CreateOrderSnapshot() 24 | } 25 | 26 | class B2BOrderCreator { 27 | ValidateDistrict() 28 | ValidateVIPProduct() 29 | GetUserInfo() 30 | GetProductDesc() 31 | DecrementStorage() 32 | CreateOrderSnapshot() 33 | } 34 | @enduml -------------------------------------------------------------------------------- /images/ch6-interface-impl.uml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/ch6-interface-impl.uml.png -------------------------------------------------------------------------------- /images/ch6-posting_list.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/ch6-posting_list.png -------------------------------------------------------------------------------- /images/ch6-snowflake-easy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/ch6-snowflake-easy.png -------------------------------------------------------------------------------- /images/ch6-snowflake.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/ch6-snowflake.png -------------------------------------------------------------------------------- /images/ch6-snoyflake.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/ch6-snoyflake.png -------------------------------------------------------------------------------- /images/ch6-sync.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/ch6-sync.png -------------------------------------------------------------------------------- /images/ch6-task-sched.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/ch6-task-sched.png -------------------------------------------------------------------------------- /images/ch6-terms.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/ch6-terms.png -------------------------------------------------------------------------------- /images/ch6-timewheel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/images/ch6-timewheel.png -------------------------------------------------------------------------------- /index.md: -------------------------------------------------------------------------------- 1 | # Go语言高级编程(Advanced Go Programming) 2 | 3 | 本书涵盖CGO、Go汇编语言、RPC实现、Web框架实现、分布式系统等高阶主题,针对Go语言有一定经验想深入了解Go语言各种高级用法的开发人员。对于刚学习Go语言的读者,建议先从[《Go语言圣经》](https://github.com/golang-china/gopl-zh)开始系统学习Go语言的基础知识。如果希望深入学习Go语言语法树结构,可以参考[《Go语法树入门——开启自制编程语言和编译器之旅》](https://github.com/chai2010/go-ast-book)。如果想从头实现一个玩具Go语言可以参考[《从头实现µGo语言》](https://github.com/wa-lang/ugo-compiler-book)。 4 | 5 | ![](cover-20190714.jpg) 6 | 7 | - 作者:柴树杉,Github [@chai2010](https://github.com/chai2010),Twitter [@chaishushan](https://twitter.com/chaishushan) 8 | - 作者:曹春晖,Github [@cch123](https://github.com/cch123) 9 | - 网址:[https://github.com/chai2010/advanced-go-programming-book](https://github.com/chai2010/advanced-go-programming-book) 10 | - 在线阅读:[https://chai2010.cn/advanced-go-programming-book](https://chai2010.cn/advanced-go-programming-book) 11 | - 豆瓣:[https://book.douban.com/subject/34442131](https://book.douban.com/subject/34442131) 12 | 13 | 购买链接: 14 | 15 | - 京东:[https://item.m.jd.com/product/12647494.html](https://item.m.jd.com/product/12647494.html) 16 | - 异步:[https://www.epubit.com/book/detail/40090](https://www.epubit.com/book/detail/40090) 17 | - 当当:[http://product.dangdang.com/27896588.html](http://product.dangdang.com/27896588.html) 18 | 19 | -------------------------------------------------------------------------------- /preface-pdf.md: -------------------------------------------------------------------------------- 1 | # 序言 2 | 3 | 2009年11月,Google发布了Go语言,在世界范围内引发了轰动。2015年和2016年中国区的Go语言大会分别在上海和北京召开,来自Go语言团队的开发人员均作了相关的报告。纵观这几年来的发展趋势,Go语言已经成为云计算、云存储时代最重要的基础编程语言。 4 | 5 | 中国的Go语言社区是全球最大的Go语言社区,我们不仅仅从一开始就始终紧跟着Go语言的发展脚步,同时也为Go语言的发展作出了自己的巨大贡献。来自中国深圳的韦光京(vcc.163@gmail.com)在2010年前后,关于MinGW的工作奠定了Go语言对Windows平台的支持,同时也奠定了CGO对Windows平台的支持。同样来自中国的Minux(minux.ma@gmail.com)则作为Go语言核心团队的成员,他参与了大量的Go语言核心设计和开发评审工作。同时还有大量的国内Go语言爱好者积极参与了BUG的汇报和修复等工作(作者也是其中之一)。 6 | 7 | 截至2018年,中国出版的Go语言相关教程有近15本之多,内容主要涵盖Go语言基础编程、Web编程、并发编程和内部源码剖析等诸多领域。但作为Go语言的资深用户,作者关注的Go语言话题远远不止这些内容。其中CGO特性实现了Go语言对C语言和C++语言的支持,使得Go语言可以无缝继承C/C++世界数十年来积累的巨大软件资产。Go汇编语言更是提供了直接访问底层机器指令的方法,让我们可以无限压榨程序中热点代码的性能。目前国内互联网公司的新兴项目已经在逐渐向Go语言生态转移,大型分布式系统的开发实战经验也是大家关心的。这些高阶或前沿特性都是作者和本书所关注的话题。 8 | 9 | 本书针对有一定Go语言经验,想深入了解Go语言各种高级用法的开发人员。对于Go语言新手,在阅读本书前建议先熟读D&K的[《The Go Programming Language》](https://gopl.io/)。最后,希望这本书能够帮助大家更深入地了解Go语言。 10 | 11 | chai2010 - 2018年 8 月 于 武汉 12 | 13 | # 致谢 14 | 15 | 首先感谢Go语言之父和每一个为Go语言提交过补丁的朋友。感谢fango的第一本以Go语言为主题的网络小说《胡文Go.ogle》和第一本中文Go语言图书《Go语言·云动力》,是你的分享让带起了大家学习Go语言的热情。感谢韦光京对Windows平台CGO的开创性工作,不然本书可能不会有专门的CGO章节。感谢为本书提交过issue或PR的朋友(特别是fuwensun、lewgun等),你们的关注和支持是作者写作的最大动力。 16 | 17 | 谢谢大家! 18 | 19 | -------------------------------------------------------------------------------- /preface.md: -------------------------------------------------------------------------------- 1 | # 序言 2 | 3 | 2009年11月,Google发布了Go语言,在世界范围内引发了轰动。2015年和2016年中国区的Go语言大会分别在上海和北京召开,来自Go语言团队的开发人员均作了相关的报告。纵观这几年来的发展趋势,Go语言已经成为云计算、云存储时代最重要的基础编程语言。 4 | 5 | 中国的Go语言社区是全球最大的Go语言社区,我们不仅仅从一开始就始终紧跟着Go语言的发展脚步,同时也为Go语言的发展作出了自己的巨大贡献。来自中国深圳的韦光京(vcc.163@gmail.com)在2010年前后,关于MinGW的工作奠定了Go语言对Windows平台的支持,同时也奠定了CGO对Windows平台的支持。同样来自中国的Minux(minux.ma@gmail.com)则作为Go语言核心团队的成员,他参与了大量的Go语言核心设计和开发评审工作。同时还有大量的国内Go语言爱好者积极参与了BUG的汇报和修复等工作(作者也是其中之一)。 6 | 7 | 截至2018年,中国出版的Go语言相关教程有近15本之多,内容主要涵盖Go语言基础编程、Web编程、并发编程和内部源码剖析等诸多领域。但作为Go语言的资深用户,作者关注的Go语言话题远远不止这些内容。其中CGO特性实现了Go语言对C语言和C++语言的支持,使得Go语言可以无缝继承C/C++世界数十年来积累的巨大软件资产。Go汇编语言更是提供了直接访问底层机器指令的方法,让我们可以无限压榨程序中热点代码的性能。目前国内互联网公司的新兴项目已经在逐渐向Go语言生态转移,大型分布式系统的开发实战经验也是大家关心的。这些高阶或前沿特性都是作者和本书所关注的话题。 8 | 9 | 本书针对有一定Go语言经验,想深入了解Go语言各种高级用法的开发人员。对于Go语言新手,在阅读本书前建议先熟读D&K的[《The Go Programming Language》](https://gopl.io/)。最后,希望这本书能够帮助大家更深入地了解Go语言。 10 | 11 | chai2010 - 2018年 8 月 于 武汉 12 | 13 | # 致谢 14 | 15 | 首先感谢Go语言之父和每一个为Go语言提交过补丁的朋友。感谢fango的第一本以Go语言为主题的网络小说《胡文Go.ogle》和第一本中文Go语言图书《Go语言·云动力》,是你的分享让带起了大家学习Go语言的热情。感谢韦光京对Windows平台CGO的开创性工作,不然本书可能不会有专门的CGO章节。感谢为本书提交过issue或PR的朋友(特别是fuwensun、lewgun等),你们的关注和支持是作者写作的最大动力。 16 | 17 | 谢谢大家! 18 | -------------------------------------------------------------------------------- /toutiao-318517-small.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/toutiao-318517-small.jpg -------------------------------------------------------------------------------- /toutiao-318517.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/toutiao-318517.jpg -------------------------------------------------------------------------------- /weappCode-qq-ke.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/weappCode-qq-ke.jpg -------------------------------------------------------------------------------- /weixin-guanggu-coder-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/weixin-guanggu-coder-logo.png -------------------------------------------------------------------------------- /weixin-guanggu-coder.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/advanced-go-programming-book/75e5cce81a006a66d5e01580d9af2841397ff3e8/weixin-guanggu-coder.jpg --------------------------------------------------------------------------------