├── .editorconfig ├── .github ├── ISSUE_TEMPLATE.md └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── SUMMARY.md ├── appendix ├── appendix-a-trap.md ├── appendix-b-ref.md ├── appendix-c-author.md └── readme.md ├── book.json ├── 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-ide.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-py-module.md ├── ch2-11-link.md ├── ch2-12-faq.md ├── ch2-xx-go-get-friendly.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-funcdata-pcdata.md ├── ch3-08-c-preprocessors.md ├── ch3-09-core-type.md ├── ch3-10-runtime-func.md ├── ch3-11-call-c-leaf-func.md ├── ch3-12-avx-sse-jit.md ├── ch3-13-arm.md ├── ch3-14-faq.md ├── pkg.go └── readme.md ├── ch4-mobile └── readme.md ├── ch6-web ├── ch6-01-introduction.md ├── ch6-02-router.md ├── ch6-03-middleware.md ├── ch6-04-validator.md ├── ch6-05-database.md ├── ch6-06-rpc.md ├── ch6-07-ratelimit.md ├── ch6-08-layout-of-web-project.md ├── ch6-09-interface-and-web.md ├── ch6-10-dist-config.md ├── ch6-11-service-discovery.md ├── ch6-12-load-balance.md ├── ch6-13-circuit-breaker.md ├── ch6-14-monitor.md ├── ch6-15-extend.md ├── ch6-16-test-and-mock.md └── readme.md ├── chx-unknown └── readme.md ├── cover.png ├── doc.go ├── examples ├── ch1-01 │ └── hello │ │ └── hello.go ├── ch1-02 │ ├── hello-alef │ │ └── hello.alef │ ├── hello-b │ │ └── main.b │ ├── hello-c-01 │ │ └── hello-c-01.c │ ├── hello-c-02 │ │ └── hello-c-02.c │ ├── hello-c-03 │ │ └── hello-c-03.c │ ├── hello-c-04 │ │ └── hello-c-04.c │ ├── hello-go-200806 │ │ └── hello.go.txt │ ├── hello-go-20080627 │ │ └── hello.go.txt │ ├── hello-go-20080811 │ │ └── hello.go.txt │ ├── hello-go-20081024 │ │ └── hello.go.txt │ ├── hello-go-20090915 │ │ └── hello.go.txt │ ├── hello-go-20091211 │ │ └── hello.go │ ├── hello-go-asm │ │ ├── hello.go │ │ └── hello_amd64.s │ ├── hello-go-cgo │ │ └── hello.go │ ├── hello-go-swig │ │ ├── hello.cc │ │ ├── hello.go │ │ └── hello.swigcxx │ ├── hello-go-v2 │ │ └── hello.go │ ├── hello-limbo │ │ └── hello.limbo │ ├── hello-newsqueak │ │ └── hello.newsqueak │ └── prime-newsqueak │ │ └── prime.newsqueak ├── ch2-01-quick-guide │ ├── 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-04-func │ └── return-go-ptr │ │ └── main.go ├── ch2-05-internal │ ├── 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-06-qsort │ ├── 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-08-class │ ├── 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-09-so-and-lib │ ├── 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-10-py │ ├── hello-py │ │ ├── Makefile │ │ ├── gopkg.h │ │ ├── main.go │ │ └── py3-config.go │ └── hello-so │ │ ├── Makefile │ │ ├── _test_so.c │ │ ├── hello.py │ │ ├── main.go │ │ └── say-hello.h ├── ch2-xx-08 │ ├── 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 ├── ch2-xx │ └── 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-01-quick-guide │ ├── 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-xx │ ├── 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 │ ├── 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 ├── images ├── Makefile ├── appendix-c-chai2010.jpg ├── by-nc-sa-4.0-88x31.png ├── ch1-01-go-family-tree-x.dot ├── ch1-01-go-family-tree-x.dot.png ├── ch1-01-go-family-tree.png ├── ch1-01-go-father.jpg ├── ch1-01-go-history.png ├── ch1-01-go-log04.png ├── ch1-02-alef.png ├── ch1-02-prime-sieve.png ├── ch1-03-array-4int.png ├── ch1-03-slice-1.png ├── ch1-03-string-1.png ├── ch1-03-string-2.png ├── ch1-04-init.png ├── ch1-08-ConEmu.png ├── ch1-08-TextMate-1.png ├── ch1-08-atom-01.png ├── ch1-08-ios-textastic-02.png ├── ch1-08-ios-textastic.png ├── ch1-08-ios-working-copy-02.png ├── ch1-08-ios-working-copy.png ├── ch1-08-macos-textastic.png ├── ch1-08-npp-auto-completion.png ├── ch1-08-npp-go-asm.png ├── ch1-08-npp-go.png ├── ch1-08-npp-proto.png ├── ch1-08-vscode-01.png ├── ch1-08-vscode-02.jpg ├── ch2-call-c-sum-v1.plantuml ├── ch2-call-c-sum-v1.uml.png ├── ch2-call-c-sum-v2.plantuml ├── ch2-call-c-sum-v2.uml.png ├── ch2-cgo-generated-files.dot ├── ch2-cgo-generated-files.dot.png ├── ch2-int32-to-char-ptr.plantuml ├── ch2-int32-to-char-ptr.uml.png ├── ch2-qsort-v2.plantuml ├── ch2-qsort-v2.uml.png ├── ch2-x-ptr-to-y-ptr.plantuml ├── ch2-x-ptr-to-y-ptr.uml.png ├── ch2-x-slice-to-y-slice.plantuml ├── ch2-x-slice-to-y-slice.uml.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-08-controller-logic-dao.png ├── ch6-08-frontend-backend.png ├── ch6-08-plugin-arch.jpg └── ch6-controller-logic-dao-storage.plantuml ├── server.go └── talks └── README.md /.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 = true 15 | 16 | [*] 17 | indent_style = tab 18 | indent_size = 4 19 | tab_width = 4 20 | 21 | [*.{go,ts,js,c,cc,cpp,h,py,proto}] 22 | charset = utf-8 23 | indent_style = tab 24 | tab_width = 4 25 | 26 | # Matches the exact files either package.json or .travis.yml 27 | [{package.json,.travis.yml}] 28 | indent_style = space 29 | indent_size = 2 30 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Expected Behavior 2 | 3 | ## Actual Behavior 4 | 5 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Description 2 | 3 | A few sentences describing the overall goals of the pull request's commits. 4 | 5 | ## Designs 6 | 7 | If it's a feature, please write your code designs here. 8 | 9 | ## Notes to reviewers 10 | 11 | Review the following things, including but not limit to: 12 | 13 | 1. Design 14 | 2. Code (styles, magic...) -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Node rules: 2 | ## Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 3 | .grunt 4 | 5 | ## Dependency directory 6 | ## Commenting this out is preferred by some people, see 7 | ## https://docs.npmjs.com/misc/faq#should-i-check-my-node_modules-folder-into-git 8 | node_modules 9 | 10 | # Book build output 11 | _book 12 | 13 | # eBook build output 14 | *.epub 15 | *.mobi 16 | *.pdf 17 | 18 | *.o 19 | *.obj 20 | *.exe 21 | 22 | # macOS 23 | .DS_Store 24 | 25 | *.a 26 | *.lib 27 | *.so 28 | *.dll 29 | *.obj 30 | *.o 31 | a.out 32 | -------------------------------------------------------------------------------- /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 | # fix gitbook build error on macOS(node@8.x and gitbook@2.6.7) 7 | # 8 | # gitbook fetch 3.2.3 9 | # gitbook build --gitbook=3.2.3 10 | # 11 | # https://github.com/GitbookIO/gitbook/issues/1774 12 | # https://github.com/GitbookIO/gitbook-cli/blob/master/README.md 13 | # 14 | 15 | default: 16 | gitbook build 17 | 18 | macos: 19 | gitbook build --gitbook=3.2.3 20 | 21 | server: 22 | go run server.go 23 | 24 | clean: 25 | -rm -rf _book 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Go语言高级编程(Advanced Go Programming) 2 | 3 | 本书针对Go语言有一定经验,想深入了解Go语言各种高级用法的开发人员。 4 | 5 | ![](cover.png) 6 | 7 | - 作者:柴树杉 (chai2010, chaishushan@gmail.com) 8 | - 网址:https://github.com/chai2010/advanced-go-programming-book 9 | 10 | ## 在线阅读 11 | 12 | - https://www.gitbook.com/book/chai2010/advanced-go-programming-book/ 13 | - [SUMMARY.md](SUMMARY.md) 14 | 15 | ## 版权声明 16 | 17 | [Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License](http://creativecommons.org/licenses/by-nc-sa/4.0/)。 18 | 19 | ![Creative Commons License](./images/by-nc-sa-4.0-88x31.png) 20 | 21 | 22 | 严禁任何商业行为使用或引用该文档的全部或部分内容! 23 | 24 | 欢迎大家提供建议! 25 | -------------------------------------------------------------------------------- /SUMMARY.md: -------------------------------------------------------------------------------- 1 | # 目录 2 | 3 | * [第一章 语言基础](ch1-basic/readme.md) 4 | * [1.1. Go语言创世纪](ch1-basic/ch1-01-genesis.md) 5 | * [1.2. Hello, World 的革命](ch1-basic/ch1-02-hello-revolution.md) 6 | * [1.3. 数组、字符串和切片](ch1-basic/ch1-03-array-string-and-slice.md) 7 | * [1.4. 函数、方法和接口](ch1-basic/ch1-04-func-method-interface.md) 8 | * [1.5. 面向并发的内存模型](ch1-basic/ch1-05-mem.md) 9 | * [1.6. 常见的并发模式](ch1-basic/ch1-06-goroutine.md) 10 | * [1.7. 错误和异常](ch1-basic/ch1-07-error-and-panic.md) 11 | * [1.8. 配置开发环境](ch1-basic/ch1-08-ide.md) 12 | * [第二章 CGO编程](ch2-cgo/readme.md) 13 | * [2.1. 快速入门](ch2-cgo/ch2-01-hello-cgo.md) 14 | * [2.2. CGO基础](ch2-cgo/ch2-02-basic.md) 15 | * [2.3. 类型转换](ch2-cgo/ch2-03-cgo-types.md) 16 | * [2.4. 函数调用](ch2-cgo/ch2-04-func.md) 17 | * [2.5. 内部机制](ch2-cgo/ch2-05-internal.md) 18 | * [2.6. 实战: 封装qsort](ch2-cgo/ch2-06-qsort.md) 19 | * [2.7. CGO内存模型](ch2-cgo/ch2-07-memory.md) 20 | * [2.8. C++类包装](ch2-cgo/ch2-08-class.md) 21 | * [2.9. 静态库和动态库](ch2-cgo/ch2-09-static-shared-lib.md) 22 | * [2.10. Go实现Python模块](ch2-cgo/ch2-10-py-module.md) 23 | * [2.11. 编译和链接参数](ch2-cgo/ch2-11-link.md) 24 | * [2.12. 补充说明](ch2-cgo/ch2-12-faq.md) 25 | * [第三章 汇编语言](ch3-asm/readme.md) 26 | * [3.1. 快速入门](ch3-asm/ch3-01-basic.md) 27 | * [3.2. 冯·诺伊曼计算机(TODO)](ch3-asm/ch3-02-arch.md) 28 | * [3.3. 常量和变量(TODO)](ch3-asm/ch3-03-const-and-var.md) 29 | * [3.4. 函数(TODO)](ch3-asm/ch3-04-func.md) 30 | * [3.5. 控制流(TODO)](ch3-asm/ch3-05-control-flow.md) 31 | * [3.6. 再论函数(TODO)](ch3-asm/ch3-06-func-again.md) 32 | * [3.7. FUNCDATA和PCDATA(TODO)](ch3-asm/ch3-07-funcdata-pcdata.md) 33 | * [3.8. C预处理器(TODO)](ch3-asm/ch3-08-c-preprocessors.md) 34 | * [3.9. Go核心对象结构(TODO)](ch3-asm/ch3-09-core-type.md) 35 | * [3.10. runtime内置函数(TODO)](ch3-asm/ch3-10-runtime-func.md) 36 | * [3.11. 调用C函数(TODO)](ch3-asm/ch3-11-call-c-leaf-func.md) 37 | * [3.12. AVX/SSE/JIT高级优化(TODO)](ch3-asm/ch3-12-avx-sse-jit.md) 38 | * [3.13. ARM汇编(TODO)](ch3-asm/ch3-13-arm.md) 39 | * [3.14. 补充说明(TODO)](ch3-asm/ch3-14-faq.md) 40 | * [第四章 移动平台(TODO)](ch4-mobile/readme.md) 41 | * [第六章 Go和Web](ch6-web/readme.md) 42 | * [6.1. Web开发简介](ch6-web/ch6-01-introduction.md) 43 | * [6.2. Router请求路由](ch6-web/ch6-02-router.md) 44 | * [6.3. Middleware中间件](ch6-web/ch6-03-middleware.md) 45 | * [6.4. Validator请求校验](ch6-web/ch6-04-validator.md) 46 | * [6.5. Database和数据库打交道](ch6-web/ch6-05-database.md) 47 | * [附录](appendix/readme.md) 48 | * [附录A: Go语言常见坑](appendix/appendix-a-trap.md) 49 | * [附录B: 参考资料](appendix/appendix-b-ref.md) 50 | * [附录C: 作者简介](appendix/appendix-c-author.md) 51 | -------------------------------------------------------------------------------- /appendix/appendix-b-ref.md: -------------------------------------------------------------------------------- 1 | # 附录B:参考资料 2 | 3 | ## 参考网站 4 | 5 | - Go语言官网: https://golang.org 6 | - SWIG官网: http://swig.org 7 | - GopherJS官网: http://www.gopherjs.org 8 | - GRPC官网: http://www.grpc.io 9 | - rsc博客: http://research.swtch.com 10 | 11 | ## 参考书目 12 | 13 | - 《Go语言圣经》: https://gopl.io 14 | - 《Go语言圣经(中文版)》: https://github.com/golang-china/gopl-zh 15 | - 《Go语言·云动力》: http://www.ituring.com.cn/book/1040 16 | - 《Go语言编程》: http://www.ituring.com.cn/book/967 17 | - 《Go语言程序设计》: http://www.ptpress.com.cn/Book.aspx?id=35714 18 | - 《C程序设计语言》: http://product.china-pub.com/14975 19 | - 《汇编语言:基于X86处理器》: http://product.china-pub.com/4934543 20 | - 《现代x86汇编语言程序设计》: http://product.china-pub.com/5006762 21 | - 《深入理解程序设计:使用Linux汇编语言》: http://product.china-pub.com/3768972 22 | - 《代码的未来》: http://product.china-pub.com/3767536 23 | 24 | -------------------------------------------------------------------------------- /appendix/appendix-c-author.md: -------------------------------------------------------------------------------- 1 | # 附录C:作者简介 2 | 3 | - **[柴树杉(网络ID:chai2010)](https://github.com/chai2010)** 是国内第一批Go语言爱好者,创建了最早的QQ讨论组和golang-china邮件列表,组织 [Go语言官方文档](https://github.com/golang-china) 和 [《Go语言圣经》](https://github.com/golang-china/gopl-zh) 的翻译工作,**Go语言代码的贡献者**,并开源了诸多 [Go语言相关的资源](https://github.com/chai2010?language=go&tab=repositories&type=source) 。 4 | -------------------------------------------------------------------------------- /appendix/readme.md: -------------------------------------------------------------------------------- 1 | # 附录 2 | 3 | 附录部分主要包含量三个部分:第一部分是摘录量一些Go语言常见的坑和解决方案;第二部分是参考网站和参考数目;第三部分是作者信息。 4 | -------------------------------------------------------------------------------- /book.json: -------------------------------------------------------------------------------- 1 | { 2 | "gitbook": "2.x", 3 | "title": "Go语言高级编程", 4 | "description": "Go语言高级编程", 5 | "language": "zh-cn", 6 | 7 | "structure": { 8 | "readme": "README.md" 9 | }, 10 | "plugins": [ 11 | "-search" 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /ch1-basic/ch1-01-genesis.md: -------------------------------------------------------------------------------- 1 | # 1.1. Go语言创世纪 2 | 3 | Go语言最初由Google公司的Robert Griesemer、Ken Thompson和Rob Pike三个大牛于2007年开始设计发明,设计新语言的最初的洪荒之力来自于对超级复杂的C++11特性的吹捧报告的鄙视,最终的目标是设计网络和多核时代的C语言。到2008年中期,语言的大部分特性设计已经完成,并开始着手实现编译器和运行时,大约在这一年Russ Cox作为主力开发者加入。到了2010年,Go语言已经逐步趋于稳定,并在9月正式发布Go语言并开源了代码。 4 | 5 | ![](../images/ch1-01-go-father.jpg) 6 | 7 | Go语言很多时候被描述为“类C语言”,或者是“21世纪的C语言”。从各种角度看,Go语言确实是从C语言继承了相似的表达式语法、控制流结构、基础数据类型、调用参数传值、指针等诸多编程思想,还有彻底继承和发扬了C语言简单直接的暴力编程哲学等。下面是《Go语言圣经》中给出的Go语言的基因图谱,我们可以从中看到有哪些编程语言对Go语言产生了影响。 8 | 9 | ![](../images/ch1-01-go-family-tree.png) 10 | 11 | 首先看基因图谱的左边一支。可以明确看出Go语言的并发特性是由贝尔实验室的Hoare于1978年发布的CSP理论演化而来。其后,CSP并发模型在Squeak/NewSqueak和Alef等编程语言中逐步完善并走向实际应用,最终这些设计经验被消化并吸收到了Go语言中。业界比较熟悉的Erlang编程语言的并发编程模型也是CSP理论的另一种实现。 12 | 13 | 再看基因图谱的中间一支。中间一支主要包含了Go语言中面向对象和包特性的演化历程。Go语言中包和接口以及面向对象等特性则继承自Niklaus Wirth所设计的Pascal语言以及其后所的衍生的相关编程语言。其中包的概念、包的导入和声明等语法主要来自于Modula-2编程语言,面向对象特性所提供的方法的声明语法等则来自于Oberon编程语言。最终Go语言演化出了自己特有的支持鸭子面向对象模型的隐式接口等诸多特性。 14 | 15 | 最后是基因图谱的右边一支,这是对C语言的致敬。Go语言是对C语言最彻底的一次扬弃,不仅仅是语法和C语言有着很多差异,最重要的是舍弃了C语言中灵活但是危险的指针运算。而且,Go语言还重新设计了C语言中部分不太合理运算符的优先级,并在很多细微的地方都做了必要的打磨和改变。当然,C语言中少即是多、简单直接的暴力编程哲学则被Go语言更彻底地发扬光大了(Go语言居然只有25个关键字,sepc语言规范还不到50页))。 16 | 17 | Go语言其它的一些特性零散地来自于其他一些编程语言;比如iota语法是从APL语言借鉴,词法作用域与嵌套函数等特性来自于Scheme语言(和其他很多编程语言)。Go语言中也有很多自己发明创新的设计。比如Go语言的切片为轻量级动态数组提供了有效的随机存取的性能,这可能会让人联想到链表的底层的共享机制。还有Go语言新发明的defer语句(Ken发明)也是神来之笔。 18 | 19 | ## 来自贝尔实验室特有基因 20 | 21 | 作为Go语言标志性的并发编程特性则来自于贝尔实验室的Tony Hoare于1978年发表鲜为外界所知的关于并发研究的基础文献:顺序通信进程( communicating sequential processes ,缩写为CSP)。在最初的CSP论文中,程序只是一组没有中间共享状态的平行运行的处理过程,它们之间使用管道进行通信和控制同步。Tony Hoare的CSP并发模型只是一个用于描述并发性基本概念的描述语言,它并不是一个可以编写可执行程序的通用编程语言。 22 | 23 | CSP并发模型最经典的实际应用是来自爱立信发明的Erlang编程语言。不过在Erlang将CSP理论作为并发编程模型的同时,同样来自贝尔实验室的Rob Pike以及其同事也在不断尝试将CSP并发模型引入当时的新发明的编程语言中。他们第一次尝试引入CSP并发特性的编程语言叫Squeak(老鼠的叫声),是一个用于提供鼠标和键盘事件处理的编程语言,在这个语言中管道是静态创建的。然后是改进版的Newsqueak语言(新版老鼠的叫声),新提供了类似C语言语句和表达式的语法,还有类似Pascal语言的推导语法。Newsqueak是一个带垃圾回收的纯函数式语言,它再次针对键盘、鼠标和窗口事件管理。但是在Newsqueak语言中管道已经是动态创建的,管道属于第一类值、可以保存到变量中。然后是Alef编程语言(Alef也是C语言之父Ritchie比较喜爱的编程语言),Alef语言试图将Newsqueak语言改造为系统编程语言,但是因为缺少垃圾回收机制而导致并发编程很痛苦(这也是继承C语言手工管理内存的代价)。在Aelf语言之后还有一个叫Limbo的编程语言(地狱的意思),这是一个运行在虚拟机中的脚本语言。Limbo语言是Go语言最接近的祖先,它和Go语言有着最接近的语法。到设计Go语言时,Rob Pike在CSP并发编程模型的实践道路上已经积累了几十年的经验,关于Go语言并发编程的特性完全是信手拈来,新编程语言的到来也是水到渠成了。 24 | 25 | 可以从Go语言库早期代码库日志可以看出最直接的演化历程(Git用`git log --before={2008-03-03} --reverse`命令查看): 26 | 27 | ![](../images/ch1-01-go-log04.png) 28 | 29 | 从早期提交日志中也可以看出,Go语言是从Ken Thompson发明的B语言、Dennis M. Ritchie发明的C语言逐步演化过来的,它首先是C语言家族的成员,因此很多人将Go语言称为21世纪的C语言。 30 | 31 | 下面是Go语言中来自贝尔实验室特有并发编程基因的演化过程: 32 | 33 | ![](../images/ch1-01-go-history.png) 34 | 35 | 纵观整个贝尔实验室的编程语言的发展进程,从B语言、C语言、Newsqueak、Alef、Limbo语言一路走来,Go语言继承了来着贝尔实验室的半个世纪的软件设计基因,终于完成了C语言革新的使命。纵观这几年来的发展趋势,Go语言已经成为云计算、云存储时代最重要的基础编程语言。 36 | 37 | ## 你好, 世界 38 | 39 | 按照惯例,介绍所有编程语言的第一个程序都是“Hello, World!”。虽然本教假设读者已经了解了Go语言,但是我们还是不想打破这个惯例(因为这个传统正是从Go语言的前辈C语言传承而来的)。不过,Go语言的这个程序输出的是中文“你好, 世界!”。 40 | 41 | ```Go 42 | package main 43 | 44 | import "fmt" 45 | 46 | func main() { 47 | fmt.Println("你好, 世界!") 48 | } 49 | ``` 50 | 51 | 将以上代码保存到`hello.go`文件中。因为代码中有非ASCII的中文字符,我们需要将文件的编码显式指定为无BOM的UTF8编码格式(源文件采用UTF8编码是Go语言规范所要求的)。然后进入命令行并切换到`hello.go`文件所在的目录。目前我们可以将Go语言当作脚本语言,在命令行中直接输入`go run hello.go`来运行程序。如果一切正常的话。应该可以在命令行看到输出"你好, 世界!"的结果。 52 | 53 | 现在,让我们简单介绍一下程序。所有的Go程序,都是由最基本的函数和变量构成,函数和变量被组织到一个个单独的Go源文件中,这些源文件再按照作者的意图组织成合适的package,最终这些package再有机地组成一个完整的Go语言程序。其中,函数用于包含一系列的语句(指明要执行的操作序列),以及执行操作时存放数据的变量。我们这个程序中函数的名字是main。虽然Go语言中,函数的名字没有太多的限制,但是main包中的main函数默认是每一个可执行程序的入口。而package则用于包装和组织相关的函数、变量和常量。在使用一个package之前,我们需要使用import语句导入包。例如,我们这个程序中导入了fmt包(fmt是format单词的缩写,表示格式化相关的包),然后我们才可以使用fmt包中的Println函数。 54 | 55 | 而双引号包含的“你好, 世界!”则是Go语言的字符串面值常量。和C语言中的字符串不同,Go语言中的字符串内容是不可变更的。在以字符串作为参数传递给fmt.Println函数时,字符串的内容并没有被复制——传递的仅仅是字符串的地址和长度(字符串的结构在`reflect.StringHeader`中定义)。在Go语言中,函数参数都是以复制的方式(不支持以引用的方式)传递(比较特殊的是,Go语言闭包函数对外部变量是以引用的方式使用)。 56 | 57 | -------------------------------------------------------------------------------- /ch1-basic/readme.md: -------------------------------------------------------------------------------- 1 | # 第一章 语言基础 2 | 3 | 本章首先简要介绍Go语言的发展历史,并较详细地分析了“Hello World”程序在各个祖先语言中演化过程。然后,对以数组、字符串和切片为代表的基础结构,对以函数、方法和接口所体现的面向过程和鸭子对象的编程,以及Go语言特有的并发编程模型和错误处理哲学做了简单介绍。最后,针对macOS、Windows、Linux几个主流的开发平台,推荐了几个较友好的Go语言编辑器和集成开发环境,因为好的工具可以极大地提高我们的效率。 4 | -------------------------------------------------------------------------------- /ch2-cgo/ch2-11-link.md: -------------------------------------------------------------------------------- 1 | # 2.11. 编译和链接参数 2 | 3 | 编译和链接参数是每一个C/C++程序员需要经常面对的问题。构建每一个C/C++应用均需要经过编译和链接两个步骤,CGO也是如此。 4 | 本节我们将简要讨论CGO中经常用到的编译和链接参数的用法。 5 | 6 | ## 编译参数:CFLAGS/CPPFLAGS/CXXFLAGS 7 | 8 | 编译参数主要是头文件的检索路径,预定义的宏等参数。理论上来说C和C++是完全独立的两个编程语言,它们可以有着自己独立的编译参数。 9 | 但是因为C++语言对C语言做了深度兼容,甚至可以将C++理解为C语言的超集,因此C和C++语言之间又会共享很多编译参数。 10 | 因此CGO提供了CFLAGS/CPPFLAGS/CXXFLAGS三种参数,其中CFLAGS对应C语言编译参数(以`.c`后缀名)、 11 | CPPFLAGS对应C/C++ 代码编译参数(*.c,*.cc,*.cpp,*.cxx)、CXXFLAGS对应纯C++编译参数(*.cc,*.cpp,*.cxx)。 12 | 13 | ## 链接参数:LDFLAGS 14 | 15 | 链接参数主要包含要链接库的检索目录和要链接库的名字。因为历史遗留问题,链接库不支持相对路径,我们必须为链接库指定绝对路径。 16 | cgo 中的 ${SRCDIR} 为当前目录的绝对路径。经过编译后的C和C++目标文件格式是一样的,因此LDFLAGS对应C/C++共同的链接参数。 17 | 18 | ## pkg-config 19 | 20 | 为不同C/C++库提供编译和链接参数是一项非常繁琐的工作,因此cgo提供了对应`pkg-config`工具的支持。 21 | 我们可以通过`#cgo pkg-config xxx`命令来生成xxx库需要的编译和链接参数,其底层通过调用 22 | `pkg-config xxx --cflags`生成编译参数,通过`pkg-config xxx --libs`命令生成链接参数。 23 | 需要注意的是`pkg-config`工具生成的编译和链接参数是C/C++公用的,无法做更细的区分。 24 | 25 | `pkg-config`工具虽然方便,但是有很多非标准的C/C++库并没有实现对其支持。 26 | 这时候我们可以手工为`pkg-config`工具创建对应库的编译和链接参数实现支持。 27 | 28 | 比如有一个名为xxx的C/C++库,我们可以手工创建`/usr/local/lib/pkgconfig/xxx.bc`文件: 29 | 30 | ``` 31 | Name: xxx 32 | Cflags:-I/usr/local/include 33 | Libs:-L/usr/local/lib –lxxx2 34 | ``` 35 | 36 | 其中Name是库的名字,Cflags和Libs行分别对应xxx使用库需要的编译和链接参数。如果bc文件在其它目录, 37 | 可以通过PKG_CONFIG_PATH环境变量指定`pkg-config`工具的检索目录。 38 | 39 | 而对应cgo来说,我们甚至可以通过PKG_CONFIG 环境变量可指定自定义的pkg-config程序。 40 | 如果是自己实现CGO专用的pkg-config程序,只要处理`--cflags`和`--libs`两个参数即可。 41 | 42 | 下面的程序是macos系统下生成Python3的编译和链接参数: 43 | 44 | ```go 45 | // py3-config.go 46 | func main() { 47 | for _, s := range os.Args { 48 | if s == "--cflags" { 49 | out, _ := exec.Command("python3-config", "--cflags").CombinedOutput() 50 | out = bytes.Replace(out, []byte("-arch"), []byte{}, -1) 51 | out = bytes.Replace(out, []byte("i386"), []byte{}, -1) 52 | out = bytes.Replace(out, []byte("x86_64"), []byte{}, -1) 53 | fmt.Print(string(out)) 54 | return 55 | } 56 | if s == "--libs" { 57 | out, _ := exec.Command("python3-config", "--ldflags").CombinedOutput() 58 | fmt.Print(string(out)) 59 | return 60 | } 61 | } 62 | } 63 | ``` 64 | 65 | 然后通过以下命令构建并使用自定义的`pkg-config`工具: 66 | 67 | ``` 68 | $ go build -o py3-config py3-config.go 69 | $ PKG_CONFIG=./py3-config go build -buildmode=c-shared -o gopkg.so main.go 70 | ``` 71 | 72 | 具体的细节可以参考Go实现Python模块章节。 73 | 74 | ## go get 链 75 | 76 | 在使用`go get`获取Go语言包的同时会获取包依赖的包。比如A包依赖B包,B包依赖C包,C包依赖D包: 77 | `pkgA -> pkgB -> pkgC -> pkgD -> ...`。再go get获取A包之后会依次线获取BCD包。 78 | 如果在获取B包之后构建失败,那么将导致链条的断裂,从而导致A包的构建失败。 79 | 80 | 链条断裂的原因有很多,其中常见的原因有: 81 | 82 | - 不支持某些系统, 编译失败 83 | - 依赖 cgo, 用户没有安装 gcc 84 | - 依赖 cgo, 但是依赖的库没有安装 85 | - 依赖 pkg-config, windows 上没有安装 86 | - 依赖 pkg-config, 没有找到对应的 bc 文件 87 | - 依赖 自定义的 pkg-config, 需要额外的配置 88 | - 依赖 swig, 用户没有安装 swig, 或版本不对 89 | 90 | 仔细分析可以发现,失败的原因中和CGO相关的问题占了绝大多数。这并不是偶然现象, 91 | 自动化构建C/C++代码一直是一个世界难题,到目前位置也没有出现一个大家认可的统一的C/C++管理工具。 92 | 93 | 因为用了cgo,比如gcc等构建工具是必须安装的,同时尽量要做到对主流系统的支持。 94 | 如果依赖的C/C++包比较小并且有源代码的前提下,可以优先选择从代码构建。 95 | 96 | 比如`github.com/chai2010/webp`包通过为每个C/C++源文件在当前包建立关键文件实现零配置依赖: 97 | 98 | ``` 99 | // z_libwebp_src_dec_alpha.c 100 | #include "./internal/libwebp/src/dec/alpha.c" 101 | ``` 102 | 103 | 因此在编译`z_libwebp_src_dec_alpha.c`文件时,会编译libweb原生的代码。 104 | 其中的依赖是相对目录,对于不同的平台支持可以保持最大的一致性。 105 | 106 | ## 多个非main包中导出C函数 107 | 108 | 官方文档说明导出的Go函数要放main包,但是真实情况是其它包的Go导出函数也是有效的。 109 | 因为导出后的Go函数就可以当作C函数使用,所以必须有效。但是不同包导出的Go函数将在同一个全局的名字空间,因此需要小心避免重名的问题。 110 | 如果是从不同的包导出Go函数到C语言空间,那么cgo自动生成的`_cgo_export.h`文件将无法包含全部到处的函数声明, 111 | 我们必须通过手写头文件的方式什么导出的全部函数。 112 | -------------------------------------------------------------------------------- /ch2-cgo/ch2-12-faq.md: -------------------------------------------------------------------------------- 1 | # 2.12. 补充说明 2 | 3 | 为何要话费巨大的精力学习CGO是一个问题。任何技术和语言都有它自身的优点和不足,Go语言不是银弹,它无法解决全部问题。而通过CGO可以继承C/C++将近半个世纪的软件遗产,通过CGO可以用Go给其它系统写C接口的共享库,通过CGO技术可以让Go语言编写的代码可以很好地融入现有的软件生态——而现在的软件正式建立在C/C++语言之上的。因此说CGO是一个保底的后备技术,它是Go的一个重量级的替补技术,值得任何一个严肃的Go语言开发人员学习。 4 | 5 | 本章讨论了CGO的一些常见用法,并给出相关的例子。关于CGO有几点补充:如果有纯Go的解决方法就不要使用CGO;CGO中涉及的C和C++构建问题非常繁琐;CGO有一定的限制无法实现解决全部的问题;不要试图越过CGO的一些限制。而且CGO只是一种官方提供并推荐的Go语言和C/C++交互的方法。如果是使用的gccgo的版本,可以通过gccgo的方式实现Go和C/C++的交互。同时SWIG也是一种选择,并对C++诸多特性提供了支持。 6 | 7 | -------------------------------------------------------------------------------- /ch2-cgo/ch2-xx-go-get-friendly.md: -------------------------------------------------------------------------------- 1 | # 2.6. CGO包的组织(Doing) 2 | 3 | 凡事都有两面性,CGO虽然是继承了C/C++庞大的生态资源,同时也带来了C/C++语言的诸多问题。第一个遇到的重要问题是如何打包CGO中对用到的C/C++库或代码的依赖。很多用户对Go语言的第一映像是构建和运行都非常快速,甚至可以当中一个脚本语言来使用。但是这种映像的前提是程序要能够正常构建,如何正确构建一个使用了CGO特性的Go语言包对很多用户是一个挑战。 4 | 5 | ## 常见的C和C++编译问题 6 | 7 | 在真实世界中C/C++一般是混合存在的。编译这类C/C++混合代码遇到的问题也是CGO经常需要解决的问题。混合C/C++代码的构建和组织的有两个原则:一是C/C++头文件最小化;二是C/C++编译参数和头文件分离。 8 | 9 | 原本的C语言世界是简单的,头文件也是简单的。当C++引入了函数重载(一个函数名有多个实现)后头文件也变得复杂起来。主要的原因是C++为了支持多个有着不同参数类型的同名函数,在生成目标文件时要对应不同的链接符号。简言之,C++中在编译阶段默认采用和C语言不同的名字修饰规则,同时支持C语言采用的名字修饰规则。 10 | 11 | 因为cgo只支持C语言语法,因此cgo也只能包含C语言的头文件。如果这个C语言头文件没有针对C++做过特殊的处理,那么在被其它的C++代码包含时需要放到`extern "C" { ... }`括号中(这是C++针对兼容C语言而增加的语法)。 12 | 13 | 编译C/C++源文件时,`.c`后缀名的对应是C语言代码,其它的一般是C++代码。C和C++代码编译时有着不同的编译选项,在`#cgo`指令中,CFLAGS对应C语言的编译选项,CPPFLAGS对应C和C++共有的编译选项,CXXFLAGS则对于C++特有的编译参数。C/C++源文件编译后成为一个个目标文件,C/C++的目标文件没有区别,共同使用LDFALAGS表示链接选项。 14 | 15 | 需要说明的是,如果C++代码中使用了C++11或更新的特性,需要在C++编译选项中指明,否则会导致编译错误。 16 | 17 | 18 | 19 | ## 依赖二进制库 20 | 21 | 最简单的CGO程序是没有任何的依赖,仅仅只是通过`import "C"`语句表示启用CGO特性: 22 | 23 | ```go 24 | // hello.go 25 | package main 26 | 27 | import "C" 28 | 29 | func main() { 30 | println("hello cgo") 31 | } 32 | ``` 33 | 34 | 这种程序最为简单,而且又是单个文件,我们可以通过`go run hello.go`命令来直接运行。但是这个程序虽然简单,但是依然会出发cgo命令行工具,依然会触发C语言代码的编译链接的过程。最终我们的得到的可执行程序会依赖一个底层的运行时库。 35 | 36 | 在不同的操作系统下看可执行程序有哪些依赖有着不同的工具。Linux系统是ldd命令,macOS系统是otool命令,Windows下则有带节目的Depends依赖检查工具。下面是这个例子在macOS系统下默认生成的可执行程序的依赖: 37 | 38 | ``` 39 | $ go build -o a.out 40 | $ otool -L a.out 41 | a.out: 42 | /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1252.0.0) 43 | ``` 44 | 45 | 对于macOS系统,`libSystem.B.dylib`一般会包含C语言运行时库的实现。对于Linux和Windows环境应该有类似的C语言运行时库。当然普通用户很少需要关心这些细节。 46 | 47 | 但是随着Docker等容器技术的流行,如何打包一个最小化Go写的程序容器成了某些用户的追求。Go语言之所以会随着容器技术会大势流行,这是一个非常重要的因素:我们甚至在没有C语言运行时库的环境正常运行Go语言写的程序。下面是在Linux环境打包静态库版本的C语言运行时库: 48 | 49 | ``` 50 | $ go build --ldflags '-w -s -extldflags "-static"' hello.go 51 | ``` 52 | 53 | 如果现在再用Linux的ldd命令查看将不会有任何的依赖,这是一个绝对绿色的程序。 54 | 55 | 更实用的CGO包一般会依赖第三方的C/C++库。如果本地操作系统中已经安装了依赖的第三方库,那么这种情况就和依赖标准的C/C++库差不多了。但是在发布时,需要确保运行程序的目标系统也包含一致的第三方C/C++共享库。 56 | 57 | 需要注意的是,释放采用静态库版本的C/C++运行时库是最终构建用户的选择,每个cgo包本书不应该过多设置最终的构建选项(因为这可能导致不同cgo包之间的链接参数的冲突)。 58 | 59 | 60 | 61 | ## 同时打包C源码 62 | 63 | ## 打包巨量C源码的问题 64 | 65 | TODO 66 | 67 | 82 | -------------------------------------------------------------------------------- /ch2-cgo/readme.md: -------------------------------------------------------------------------------- 1 | # 第二章 CGO编程 2 | 3 | C/C++经过几十年的发展,已经积累了庞大的软件资产,它们很多久经考验而且性能已经足够优化。Go语言必须能够站在C/C++这个巨人的肩膀之上,有了海量的C/C++软件资产兜底之后,我们才可以放心愉快地用Go语言编程。C语言作为一个通用语言,很多库会选择提供一个C兼容的API,然后用其他不同的编程语言实现。Go语言通过自带的一个叫CGO的工具来支持C语言函数调用,同时我们可以用Go语言导出C动态库接口给其它语言使用。本章主要讨论CGO编程中涉及的一些问题。 4 | -------------------------------------------------------------------------------- /ch3-asm/ch3-02-arch.md: -------------------------------------------------------------------------------- 1 | # 3.2. 冯·诺伊曼 计算机(TODO) 2 | 3 | TODO 4 | -------------------------------------------------------------------------------- /ch3-asm/ch3-03-const-and-var.md: -------------------------------------------------------------------------------- 1 | # 3.2. 常量和变量(TODO) 2 | 3 | TODO 4 | -------------------------------------------------------------------------------- /ch3-asm/ch3-04-func.md: -------------------------------------------------------------------------------- 1 | # 3.4. 函数(TODO) 2 | 3 | TODO 4 | -------------------------------------------------------------------------------- /ch3-asm/ch3-05-control-flow.md: -------------------------------------------------------------------------------- 1 | # 3.5. 控制流(TODO) 2 | 3 | TODO 4 | -------------------------------------------------------------------------------- /ch3-asm/ch3-06-func-again.md: -------------------------------------------------------------------------------- 1 | # 3.6. 再论函数(TODO) 2 | 3 | TODO 4 | -------------------------------------------------------------------------------- /ch3-asm/ch3-07-funcdata-pcdata.md: -------------------------------------------------------------------------------- 1 | # 3.6. FUNCDATA和PCDATA(TODO) 2 | 3 | TODO 4 | -------------------------------------------------------------------------------- /ch3-asm/ch3-08-c-preprocessors.md: -------------------------------------------------------------------------------- 1 | # 3.8. C预处理器(TODO) 2 | 3 | TODO 4 | -------------------------------------------------------------------------------- /ch3-asm/ch3-09-core-type.md: -------------------------------------------------------------------------------- 1 | # 3.9. Go核心对象结构(TODO) 2 | 3 | TODO 4 | -------------------------------------------------------------------------------- /ch3-asm/ch3-10-runtime-func.md: -------------------------------------------------------------------------------- 1 | # 3.10. runtime内置函数(TODO) 2 | 3 | TODO 4 | 5 | 6 | -------------------------------------------------------------------------------- /ch3-asm/ch3-11-call-c-leaf-func.md: -------------------------------------------------------------------------------- 1 | # 3.11. 调用C函数(TODO) 2 | 3 | TODO 4 | -------------------------------------------------------------------------------- /ch3-asm/ch3-12-avx-sse-jit.md: -------------------------------------------------------------------------------- 1 | # 3.12. AVX/SSE/JIT高级优化(TODO) 2 | 3 | TODO 4 | -------------------------------------------------------------------------------- /ch3-asm/ch3-13-arm.md: -------------------------------------------------------------------------------- 1 | # 3.14. ARM汇编(TODO) 2 | 3 | TODO 4 | -------------------------------------------------------------------------------- /ch3-asm/ch3-14-faq.md: -------------------------------------------------------------------------------- 1 | # 3.14. 补充说明(TODO) 2 | 3 | TODO 4 | -------------------------------------------------------------------------------- /ch3-asm/pkg.go: -------------------------------------------------------------------------------- 1 | package pkg 2 | 3 | var id int = 9527 4 | -------------------------------------------------------------------------------- /ch3-asm/readme.md: -------------------------------------------------------------------------------- 1 | # 第三章 Go汇编语言 2 | 3 | Go语言中很多设计思想和工具都是传承自Plan9操作系统,Go汇编语言也是基于Plan9汇编演化而来。根据Rob Pike的介绍,大神Ken Thompson在1986年为Plan9系统编写的C语言编译器输出的汇编伪代码就是Plan9汇编的前身。所谓的Plan9汇编语言只是便于以手工方式书写该C语言编译器输出的汇编伪代码而已。 4 | 5 | 无论高级语言如何发展,作为最接近CPU的汇编语言的地方依然是无法彻底被替代的。只有通过汇编语言才能彻底挖掘CPU芯片的全部功能,因此操作系统的引导过程必须要依赖汇编语言的帮助。只有通过汇编语言才能彻底榨干CPU芯片的性能,因此很多底层的加密解密等对性能敏感的算法会考虑通过汇编语言进行性能优化。 6 | 7 | 对于每一个严肃的Gopher,Go汇编语言都是一个不可忽视的技术。因为哪怕只懂一点点汇编,也便于更好地理解计算机,将更容易理解Go语言中动态栈/接口等高级特性的实现原理。而且掌握了Go汇编语言之后,你将不用担心再被其它所谓的任何高级编程语言用户鄙视。 8 | 9 | 本章我们将以AMD64为主要开发环境,简单地探讨Go汇编语言的基础用法。 10 | 11 | -------------------------------------------------------------------------------- /ch4-mobile/readme.md: -------------------------------------------------------------------------------- 1 | # 第四章 移动平台 2 | 3 | TODO 4 | -------------------------------------------------------------------------------- /ch6-web/ch6-06-rpc.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iikira/advanced-go-programming-book/1b5310f7547a5191d4687d94e0e6a9d32be61431/ch6-web/ch6-06-rpc.md -------------------------------------------------------------------------------- /ch6-web/ch6-07-ratelimit.md: -------------------------------------------------------------------------------- 1 | # 6.7. Ratelimit 服务流量限制 2 | -------------------------------------------------------------------------------- /ch6-web/ch6-08-layout-of-web-project.md: -------------------------------------------------------------------------------- 1 | # 6.8. layout 常见大型 web 项目分层 2 | 3 | 流行的 web 框架大多数是 MVC 框架,MVC 这个概念最早由 Trygve Reenskaug 在 1978 年提出,为了能够对 GUI 类型的应用进行方便扩展,将程序划分为: 4 | 5 | 1. 控制器(Controller)- 负责转发请求,对请求进行处理。 6 | 2. 视图(View) - 界面设计人员进行图形界面设计。 7 | 3. 模型(Model) - 程序员编写程序应有的功能(实现算法等等)、数据库专家进行数据管理和数据库设计(可以实现具体的功能)。 8 | 9 | 随着时代的发展,前端也变成了越来越复杂的工程,为了更好地工程化,现在更为流行的一般是前后分离的架构。可以认为前后分离是把 V 层从 MVC 中抽离单独成为项目。这样一个后端项目一般就只剩下 M 和 C 层了。前后端之间通过 ajax 来交互,有时候要解决跨域的问题,但也已经有了较为成熟的方案。下面是一个前后分离的系统的简易交互图。 10 | 11 | ![前后分离](../images/ch6-08-frontend-backend.png) 12 | 13 | 图里的 vue 和 react 是现在前端界比较流行的两个框架,因为我们的重点不在这里,所以前端项目内的组织我们就不强调了。事实上,即使是简单的项目,业界也并没有完全遵守 MVC 功能提出者对于 M 和 C 所定义的分工。有很多公司的项目会在 controller 层塞入大量的逻辑,在 model 层就只管理数据的存储。这往往来源于对于 model 层字面含义的某种擅自引申理解。认为字面意思,这一层就是处理某种建模,而模型是什么?就是数据呗! 14 | 15 | 这种理解显然是有问题的,业务流程也算是一种“模型”,是对真实世界用户行为或者既有流程的一种建模,并非只有按格式组织的数据才能叫模型。不过按照 MVC 的创始人的想法,我们如果把和数据打交道的代码还有业务流程全部塞进 MVC 里的 M 层的话,这个 M 层又会显得有些过于臃肿。对于复杂的项目,一个 C 和一个 M 层显然是不够用的,现在比较流行的纯后端 api 模块一般采用下述划分方法: 16 | 17 | 1. Controller,与上述类似,服务入口,负责处理路由,参数校验,请求转发 18 | 2. Logic/Service,逻辑(服务)层,一般是业务逻辑的入口,可以认为从这里开始,所有的请求参数一定是合法的。业务逻辑和业务流程也都在这一层中。常见的设计中会将该层称为 Business Rules。 19 | 3. DAO/Repository,这一层主要负责和数据、存储打交道。将下层存储以更简单的函数、接口形式暴露给 Logic 层来使用。负责数据的持久化工作。 20 | 21 | 每一层都会做好自己的工作,然后用请求当前的上下文构造下一层工作所需要的结构体或其它类型参数,然后调用下一次的函数。在工作完成之后,再把处理结果一层层地传出到入口。 22 | 23 | ![controller-logic-dao](../images/ch6-08-controller-logic-dao.png) 24 | 25 | 划分为 CLD 三层之后,在 C 层我们可能还需要同时支持多种协议。本章前面讲到的 thrift、gRPC 和 http 并不是一定只选择其中一种,有时我们需要支持其中的两种,比如同一个接口,我们既需要效率较高的 thrift,也需要方便 debug 的 http 入口。这样请求的流程会变成下面这样: 26 | 27 | TODOTODO,thrift protocol -> controller -> logic -> dao|| http protocol -> controller -> logic -> dao 28 | 29 | ```go 30 | func CreateOrder(ctx context.Context, req *CreateOrderStruct) (*CreateOrderRespStruct, error) { 31 | } 32 | ``` 33 | 34 | CreateOrder 有两个参数,ctx 用来传入 trace_id 一类的需要串联请求的全局参数,req 里存储了我们创建订单所需要的所有输入信息。返回结果是一个响应结构体和错误。可以认为,我们的代码运行到 logic 层之后,就没有任何与“协议”相关的代码了。在这里你找不到 http.Request,也找不到 http.ResponseWriter,也找不到任何与 thrift 或者 gRPC 相关的字眼。 35 | 36 | ```go 37 | 38 | // in logic 39 | type CreateOrderRequest struct { 40 | OrderID `json:"order_id"` 41 | // ... 42 | } 43 | 44 | func HTTPCreateOrderHandler(wr http.ResponseWriter, r *http.Request) { 45 | var params CreateOrderRequest 46 | ctx := context.TODO() 47 | // bind data to req 48 | logicResp,err := logic.CreateOrder(ctx, ¶ms) 49 | if err != nil {} 50 | // ... 51 | } 52 | ``` 53 | 54 | 理论上我们可以用同一个 request struct 组合上不同的 tag,来达到一个 struct 来给不同的协议复用的目的。不过遗憾的是在 thrift 中,request struct 也是通过 IDL 生成的,其内容在自动生成的 ttypes.go 文件中,我们还是需要在 thrift 的入口将这个自动生成的 struct 映射到我们 logic 入口所需要的 struct 上。gRPC 也是类似。这部分代码还是需要的。 55 | 56 | 聪明的读者可能已经可以看出来了,协议细节处理这一层实际上有大量重复劳动,每一个接口在协议这一层的处理,无非是把数据从协议特定的 struct(例如 http.Request,thrift 的被包装过了) 读出来,再绑定到我们协议相关的 struct 上,再把这个 struct 映射到 logic 入口的 struct 上,这些代码实际上长得都差不多。差不多的代码都遵循着某种模式,那么我们可以对这些模式进行简单的抽象,用 codegen 来把繁复的协议处理代码从工作内容中抽离出去。 57 | 58 | 还是举个例子: 59 | 60 | ```go 61 | ``` 62 | 63 | 我们需要一个基准 request struct,来根据这个 request struct 生成我们需要的入口代码。这个基准要怎么找呢? 64 | 65 | 我们成功地使自己的项目在入口支持了多种交互协议,但是还有一些问题没有解决。本节中所叙述的分层没有将 middleware 作为项目的分层考虑进去。如果我们考虑 middleware 的话,请求的流程是什么样的? 66 | 67 | TODOTODO,这里是带上 middleware 之后的请求图。 68 | 69 | 之前我们学习的 middleware 是和 http 协议强相关的,在项目支持了多种协议之后,这种和协议强绑定的 middleware 成为了我们的瓶颈。如果我们坚持用之前的 middleware 方案的话,这里 thrift 的请求路线就还需要再多写一套 thrift 自己的 middleware,将业务无关的代码重复地写了两遍。请求流程变成了这样: 70 | 71 | TODOTODO,这里是加入 middleware 之后的多协议框架请求处理流程。 72 | 73 | 这也是很多企业项目所面临的真实问题,遗憾的是开源界并没有这样方便的多协议 middleware 解决方案。 74 | 75 | 怎么解决这个问题呢,也不麻烦。把协议处理从 controller 中独立出去,新的 middleware 写在协议处理层后面。如图: 76 | 77 | TODOTODO,这里有图,是将 middleware 后置之后的请求处理流程。 78 | 79 | 是不是感觉项目变的越来越复杂了?真实的项目就是这样一步一步,根据需求演进而来的。 80 | -------------------------------------------------------------------------------- /ch6-web/ch6-09-interface-and-web.md: -------------------------------------------------------------------------------- 1 | # 6.8. interface 和 web 编程 2 | 3 | 在项目中我们有可能遇到这样的场景:公司内的基础架构因为技术实力原因,最早是从别人那里借来的 kv 存储方案。随着公司的发展,渐渐有大牛加入,想要甩掉这个借来的包袱自研 kv 存储,但接口与之前的 kv 存储不兼容。接入时需要业务改动接入代码,怎么写代码才能让我的核心业务逻辑不受这些外部资源变化影响呢。 4 | 5 | ## interface 与依赖反转 6 | 7 | 学习 Golang 时一般对 interface 都会建立较基本的理解。从架构的角度上来讲,interface 解决的最大的问题是依赖方向问题。例如在一个典型的 web 程序中: 8 | 9 | TODOTODO 这里有图,标明控制流的方向 10 | 11 | 我们的控制流方向是从 controller -> logic -> dao,在不使用 interface 的前提下,我们在 controller 中需要 import logic 的 package,然后在 logic 中需要 import dao 的 package。这种 import 关系和控制流的方向是一致的,因为我们需要用到 a.x 函数,那么 import a 就显得自然而然了。而 import 意味着依赖,也就是说我们的依赖方向与控制流的方向是完全一致的。 12 | 13 | 从架构的角度讲,这个控制流会给我们带来很多问题: 14 | 15 | 1. dao 的变动必然会引起 logic 的变动 16 | 2. 核心的业务逻辑 logic 代码变动会给我们带来较大的风险 17 | 3. 项目的依赖于大量的外部服务、组件,难以测试 18 | 19 | 本节主要解决 1 和 2 两个问题。 20 | 21 | interface 这时候就成为了我们的救星,如果我们在 a->b 这个控制方向上不满意,不想让 b 的变化引起 a 的不适,那么我们就在 a 与 b 之间插入一层 interface。 22 | 23 | ```go 24 | controller -> logic (interfaces defined in package a) <- dao 25 | ``` 26 | 27 | 通过插入一层 interface,代码中的依赖方向发生了变化,如图: 28 | 29 | TODOTODO,这里是控制流和依赖流的示意图。 30 | 31 | 这样就可以让 logic 摆脱了对 dao 的依赖,从而将 logic 的代码保护了起来。就像 Uncle Bob 所描述的那样: 32 | 33 | ![插件化架构](../images/ch6-08-plugin-arch.jpg) 34 | 35 | dao(DB) 成为了 logic(business rules) 的 plugin(插件)。如果我们要把 dao 里的 kv 数据库从 rocksdb(假如) 替换为自研的 thrift 协议 kv 存储,那么新的 dao 实现也只要遵从之前定义好的 interface 就可以,logic 不需要任何变化。这就是所谓的插件化架构。 36 | 37 | ## 实例 38 | 39 | 稍微具体一点: 40 | 41 | ```go 42 | // src/dto 43 | type Order struct { 44 | OrderID int64 45 | UserID int64 46 | ProductID int64 47 | CreateTime time.Time 48 | } 49 | 50 | // src/logic 51 | type OrderRep interface { 52 | func Save(r dto.Order) error 53 | func Get(orderID int64) (dto.Order, error) 54 | } 55 | 56 | // one of many dependencies 57 | var orderService OrderRep 58 | 59 | // init order dependency 60 | func InitOrderService(os OrderRep) error { 61 | orderService = os 62 | } 63 | 64 | // api provided by logic 65 | func CreateOrder(orderID int64, userID int64, productID int64, createTime time.Time) error { 66 | o := Order{ 67 | OrderID : orderID, 68 | UserID : userID, 69 | ProductID : productID, 70 | CreateTime : createTime, 71 | } 72 | 73 | err := orderService.Save(o) 74 | 75 | if err != nil { 76 | // do someth 77 | return err 78 | } 79 | return nil 80 | } 81 | 82 | // src/dao/order 83 | type OrderService struct {} 84 | 85 | func (od *OrderService) Save(r dto.Order) error { 86 | // save this order 87 | return nil 88 | } 89 | 90 | func (od *OrderService) Get(orderID int64) (dto.Order, error) { 91 | // save this order 92 | return nil 93 | } 94 | 95 | // src/main 96 | func initAllDependencies() { 97 | // order service init 98 | orderService := orderdao.OrderService{} 99 | orderlogic.InitOrderService(orderService) 100 | } 101 | 102 | ``` 103 | 104 | 上面是一个简单将 order 的 dao 层和 logic 进行控制反转的例子。有了这种手段,我们可以将控制流中,logic 所有下层逻辑全部变成 logic 的插件。 105 | 106 | 用控制反转把我们的核心业务逻辑隔离出来的手段实际上也存在着一些争议,Uncle Bob 认为这是最佳实践,哪怕我们的项目模块没有那么复杂,也应该允许把这些内部的 interface 先设计好,并保留在项目中,以方便日后的扩展。但 interface 的引入多多少少会给项目带来一定程度的复杂性,而且有一部分 IDE 对 interface 的支持并不是非常好(比如非常流行的 vscode,在查找 interface 的 implementation 时就极其缓慢)。 107 | 108 | 总的来说,interface 依然是一种值得学习的方法,就算短时间内用不上。在未来某一天你被反复变动的下游逻辑恶心到的时候,大概会突然想起来可以用控制反转将变化控制在模块之内,那个时候自然对这种手段理解更为深刻了吧。 109 | -------------------------------------------------------------------------------- /ch6-web/ch6-10-dist-config.md: -------------------------------------------------------------------------------- 1 | # 6.8. Dist-config 分布式配置服务 -------------------------------------------------------------------------------- /ch6-web/ch6-11-service-discovery.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iikira/advanced-go-programming-book/1b5310f7547a5191d4687d94e0e6a9d32be61431/ch6-web/ch6-11-service-discovery.md -------------------------------------------------------------------------------- /ch6-web/ch6-12-load-balance.md: -------------------------------------------------------------------------------- 1 | # 6.12. Load-Balance 负载均衡 -------------------------------------------------------------------------------- /ch6-web/ch6-13-circuit-breaker.md: -------------------------------------------------------------------------------- 1 | # 6.9. Circuit-Breaker 熔断保护 2 | -------------------------------------------------------------------------------- /ch6-web/ch6-14-monitor.md: -------------------------------------------------------------------------------- 1 | # 6.8. Monitor metrics 和服务监控 2 | -------------------------------------------------------------------------------- /ch6-web/ch6-15-extend.md: -------------------------------------------------------------------------------- 1 | 服务准入、业务线级限流、压测谬论、api 文档化、分布式锁服务、lstio 2 | -------------------------------------------------------------------------------- /ch6-web/ch6-16-test-and-mock.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iikira/advanced-go-programming-book/1b5310f7547a5191d4687d94e0e6a9d32be61431/ch6-web/ch6-16-test-and-mock.md -------------------------------------------------------------------------------- /ch6-web/readme.md: -------------------------------------------------------------------------------- 1 | # 第六章 go 和 web 2 | 3 | 本章将会阐述 go 在 web 开发方面的现状,并以几个典型的开源 web 框架为例,带大家深入 web 框架本身的执行流程。 4 | 5 | 同时会介绍现代企业级 web 开发面临的一些问题,以及在 golang 中如何面对,并解决这些问题。 6 | 7 | -------------------------------------------------------------------------------- /chx-unknown/readme.md: -------------------------------------------------------------------------------- 1 | # 未知章节 2 | -------------------------------------------------------------------------------- /cover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iikira/advanced-go-programming-book/1b5310f7547a5191d4687d94e0e6a9d32be61431/cover.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 github_com_chai2010_advanced_go_programming_book 11 | -------------------------------------------------------------------------------- /examples/ch1-01/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 "fmt" 7 | 8 | func main() { 9 | fmt.Println("你好, 世界!") 10 | } 11 | -------------------------------------------------------------------------------- /examples/ch1-02/hello-alef/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-02/hello-b/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-02/hello-c-01/hello-c-01.c: -------------------------------------------------------------------------------- 1 | main() 2 | { 3 | printf("hello, world"); 4 | } 5 | -------------------------------------------------------------------------------- /examples/ch1-02/hello-c-02/hello-c-02.c: -------------------------------------------------------------------------------- 1 | main() 2 | { 3 | printf("hello, world\n"); 4 | } 5 | -------------------------------------------------------------------------------- /examples/ch1-02/hello-c-03/hello-c-03.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | main() 4 | { 5 | printf("hello, world\n"); 6 | } 7 | -------------------------------------------------------------------------------- /examples/ch1-02/hello-c-04/hello-c-04.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | main(void) 4 | { 5 | printf("hello, world\n"); 6 | } 7 | -------------------------------------------------------------------------------- /examples/ch1-02/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-02/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-02/hello-go-20080811/hello.go.txt: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | func main() { 4 | print("hello, world\n"); 5 | } 6 | -------------------------------------------------------------------------------- /examples/ch1-02/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-02/hello-go-20090915/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-02/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-02/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-02/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-02/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-02/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-02/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-02/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/ch1-02/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-02/hello-limbo/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-02/hello-newsqueak/hello.newsqueak: -------------------------------------------------------------------------------- 1 | print("Hello,", "World", "\n"); 2 | -------------------------------------------------------------------------------- /examples/ch1-02/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/ch2-01-quick-guide/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-01-quick-guide/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-01-quick-guide/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-01-quick-guide/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-01-quick-guide/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-01-quick-guide/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-01-quick-guide/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-04-func/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-05-internal/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-05-internal/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-05-internal/01-cgo-gen-files/_obj/_cgo_export.h: -------------------------------------------------------------------------------- 1 | /* Created by "go tool cgo" - DO NOT EDIT. */ 2 | 3 | /* package main */ 4 | 5 | 6 | #line 1 "cgo-builtin-prolog" 7 | 8 | #include /* for ptrdiff_t below */ 9 | 10 | #ifndef GO_CGO_EXPORT_PROLOGUE_H 11 | #define GO_CGO_EXPORT_PROLOGUE_H 12 | 13 | typedef struct { const char *p; ptrdiff_t n; } _GoString_; 14 | 15 | #endif 16 | 17 | /* Start of preamble from import "C" comments. */ 18 | 19 | 20 | 21 | /* End of preamble from import "C" comments. */ 22 | 23 | 24 | /* Start of boilerplate cgo prologue. */ 25 | #line 1 "cgo-gcc-export-header-prolog" 26 | 27 | #ifndef GO_CGO_PROLOGUE_H 28 | #define GO_CGO_PROLOGUE_H 29 | 30 | typedef signed char GoInt8; 31 | typedef unsigned char GoUint8; 32 | typedef short GoInt16; 33 | typedef unsigned short GoUint16; 34 | typedef int GoInt32; 35 | typedef unsigned int GoUint32; 36 | typedef long long GoInt64; 37 | typedef unsigned long long GoUint64; 38 | typedef GoInt64 GoInt; 39 | typedef GoUint64 GoUint; 40 | typedef __SIZE_TYPE__ GoUintptr; 41 | typedef float GoFloat32; 42 | typedef double GoFloat64; 43 | typedef float _Complex GoComplex64; 44 | typedef double _Complex GoComplex128; 45 | 46 | /* 47 | static assertion to make sure the file is being used on architecture 48 | at least with matching size of GoInt. 49 | */ 50 | typedef char _check_for_64_bit_pointer_matching_GoInt[sizeof(void*)==64/8 ? 1:-1]; 51 | 52 | typedef _GoString_ GoString; 53 | typedef void *GoMap; 54 | typedef void *GoChan; 55 | typedef struct { void *t; void *v; } GoInterface; 56 | typedef struct { void *data; GoInt len; GoInt cap; } GoSlice; 57 | 58 | #endif 59 | 60 | /* End of boilerplate cgo prologue. */ 61 | 62 | #ifdef __cplusplus 63 | extern "C" { 64 | #endif 65 | 66 | 67 | #ifdef __cplusplus 68 | } 69 | #endif 70 | -------------------------------------------------------------------------------- /examples/ch2-05-internal/01-cgo-gen-files/_obj/_cgo_flags: -------------------------------------------------------------------------------- 1 | _CGO_CFLAGS= 2 | -------------------------------------------------------------------------------- /examples/ch2-05-internal/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-05-internal/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-05-internal/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-05-internal/01-cgo-gen-files/_obj/hello.cgo2.c: -------------------------------------------------------------------------------- 1 | 2 | #line 1 "cgo-builtin-prolog" 3 | #include /* for ptrdiff_t and size_t below */ 4 | 5 | /* Define intgo when compiling with GCC. */ 6 | typedef ptrdiff_t intgo; 7 | 8 | typedef struct { const char *p; intgo n; } _GoString_; 9 | typedef struct { char *p; intgo n; intgo c; } _GoBytes_; 10 | _GoString_ GoString(char *p); 11 | _GoString_ GoStringN(char *p, int l); 12 | _GoBytes_ GoBytes(void *p, int n); 13 | char *CString(_GoString_); 14 | void *CBytes(_GoBytes_); 15 | void *_CMalloc(size_t); 16 | 17 | __attribute__ ((unused)) 18 | static size_t _GoStringLen(_GoString_ s) { return s.n; } 19 | 20 | __attribute__ ((unused)) 21 | static const char *_GoStringPtr(_GoString_ s) { return s.p; } 22 | 23 | 24 | 25 | #line 1 "cgo-gcc-prolog" 26 | /* 27 | If x and y are not equal, the type will be invalid 28 | (have a negative array count) and an inscrutable error will come 29 | out of the compiler and hopefully mention "name". 30 | */ 31 | #define __cgo_compile_assert_eq(x, y, name) typedef char name[(x-y)*(x-y)*-2+1]; 32 | 33 | /* Check at compile time that the sizes we use match our expectations. */ 34 | #define __cgo_size_assert(t, n) __cgo_compile_assert_eq(sizeof(t), n, _cgo_sizeof_##t##_is_not_##n) 35 | 36 | __cgo_size_assert(char, 1) 37 | __cgo_size_assert(short, 2) 38 | __cgo_size_assert(int, 4) 39 | typedef long long __cgo_long_long; 40 | __cgo_size_assert(__cgo_long_long, 8) 41 | __cgo_size_assert(float, 4) 42 | __cgo_size_assert(double, 8) 43 | 44 | extern char* _cgo_topofstack(void); 45 | 46 | #include 47 | #include 48 | 49 | 50 | #define CGO_NO_SANITIZE_THREAD 51 | #define _cgo_tsan_acquire() 52 | #define _cgo_tsan_release() 53 | 54 | -------------------------------------------------------------------------------- /examples/ch2-05-internal/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-05-internal/01-cgo-gen-files/_obj/main.cgo2.c: -------------------------------------------------------------------------------- 1 | 2 | #line 1 "cgo-builtin-prolog" 3 | #include /* for ptrdiff_t and size_t below */ 4 | 5 | /* Define intgo when compiling with GCC. */ 6 | typedef ptrdiff_t intgo; 7 | 8 | typedef struct { const char *p; intgo n; } _GoString_; 9 | typedef struct { char *p; intgo n; intgo c; } _GoBytes_; 10 | _GoString_ GoString(char *p); 11 | _GoString_ GoStringN(char *p, int l); 12 | _GoBytes_ GoBytes(void *p, int n); 13 | char *CString(_GoString_); 14 | void *CBytes(_GoBytes_); 15 | void *_CMalloc(size_t); 16 | 17 | __attribute__ ((unused)) 18 | static size_t _GoStringLen(_GoString_ s) { return s.n; } 19 | 20 | __attribute__ ((unused)) 21 | static const char *_GoStringPtr(_GoString_ s) { return s.p; } 22 | 23 | 24 | 25 | #line 1 "cgo-gcc-prolog" 26 | /* 27 | If x and y are not equal, the type will be invalid 28 | (have a negative array count) and an inscrutable error will come 29 | out of the compiler and hopefully mention "name". 30 | */ 31 | #define __cgo_compile_assert_eq(x, y, name) typedef char name[(x-y)*(x-y)*-2+1]; 32 | 33 | /* Check at compile time that the sizes we use match our expectations. */ 34 | #define __cgo_size_assert(t, n) __cgo_compile_assert_eq(sizeof(t), n, _cgo_sizeof_##t##_is_not_##n) 35 | 36 | __cgo_size_assert(char, 1) 37 | __cgo_size_assert(short, 2) 38 | __cgo_size_assert(int, 4) 39 | typedef long long __cgo_long_long; 40 | __cgo_size_assert(__cgo_long_long, 8) 41 | __cgo_size_assert(float, 4) 42 | __cgo_size_assert(double, 8) 43 | 44 | extern char* _cgo_topofstack(void); 45 | 46 | #include 47 | #include 48 | 49 | 50 | #define CGO_NO_SANITIZE_THREAD 51 | #define _cgo_tsan_acquire() 52 | #define _cgo_tsan_release() 53 | 54 | -------------------------------------------------------------------------------- /examples/ch2-05-internal/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-05-internal/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-05-internal/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-05-internal/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-05-internal/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-05-internal/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-05-internal/02-go-call-c-func/_obj/_cgo_export.h: -------------------------------------------------------------------------------- 1 | /* Created by "go tool cgo" - DO NOT EDIT. */ 2 | 3 | /* package main */ 4 | 5 | 6 | #line 1 "cgo-builtin-prolog" 7 | 8 | #include /* for ptrdiff_t below */ 9 | 10 | #ifndef GO_CGO_EXPORT_PROLOGUE_H 11 | #define GO_CGO_EXPORT_PROLOGUE_H 12 | 13 | typedef struct { const char *p; ptrdiff_t n; } _GoString_; 14 | 15 | #endif 16 | 17 | /* Start of preamble from import "C" comments. */ 18 | 19 | 20 | 21 | /* End of preamble from import "C" comments. */ 22 | 23 | 24 | /* Start of boilerplate cgo prologue. */ 25 | #line 1 "cgo-gcc-export-header-prolog" 26 | 27 | #ifndef GO_CGO_PROLOGUE_H 28 | #define GO_CGO_PROLOGUE_H 29 | 30 | typedef signed char GoInt8; 31 | typedef unsigned char GoUint8; 32 | typedef short GoInt16; 33 | typedef unsigned short GoUint16; 34 | typedef int GoInt32; 35 | typedef unsigned int GoUint32; 36 | typedef long long GoInt64; 37 | typedef unsigned long long GoUint64; 38 | typedef GoInt64 GoInt; 39 | typedef GoUint64 GoUint; 40 | typedef __SIZE_TYPE__ GoUintptr; 41 | typedef float GoFloat32; 42 | typedef double GoFloat64; 43 | typedef float _Complex GoComplex64; 44 | typedef double _Complex GoComplex128; 45 | 46 | /* 47 | static assertion to make sure the file is being used on architecture 48 | at least with matching size of GoInt. 49 | */ 50 | typedef char _check_for_64_bit_pointer_matching_GoInt[sizeof(void*)==64/8 ? 1:-1]; 51 | 52 | typedef _GoString_ GoString; 53 | typedef void *GoMap; 54 | typedef void *GoChan; 55 | typedef struct { void *t; void *v; } GoInterface; 56 | typedef struct { void *data; GoInt len; GoInt cap; } GoSlice; 57 | 58 | #endif 59 | 60 | /* End of boilerplate cgo prologue. */ 61 | 62 | #ifdef __cplusplus 63 | extern "C" { 64 | #endif 65 | 66 | 67 | #ifdef __cplusplus 68 | } 69 | #endif 70 | -------------------------------------------------------------------------------- /examples/ch2-05-internal/02-go-call-c-func/_obj/_cgo_flags: -------------------------------------------------------------------------------- 1 | _CGO_CFLAGS= 2 | -------------------------------------------------------------------------------- /examples/ch2-05-internal/02-go-call-c-func/_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_int int32 19 | 20 | type _Ctype_void [0]byte 21 | 22 | //go:linkname _cgo_runtime_cgocall runtime.cgocall 23 | func _cgo_runtime_cgocall(unsafe.Pointer, uintptr) int32 24 | 25 | //go:linkname _cgo_runtime_cgocallback runtime.cgocallback 26 | func _cgo_runtime_cgocallback(unsafe.Pointer, unsafe.Pointer, uintptr, uintptr) 27 | 28 | //go:linkname _cgoCheckPointer runtime.cgoCheckPointer 29 | func _cgoCheckPointer(interface{}, ...interface{}) 30 | 31 | //go:linkname _cgoCheckResult runtime.cgoCheckResult 32 | func _cgoCheckResult(interface{}) 33 | 34 | //go:cgo_import_static _cgo_506f45f9fa85_Cfunc_sum 35 | //go:linkname __cgofn__cgo_506f45f9fa85_Cfunc_sum _cgo_506f45f9fa85_Cfunc_sum 36 | var __cgofn__cgo_506f45f9fa85_Cfunc_sum byte 37 | var _cgo_506f45f9fa85_Cfunc_sum = unsafe.Pointer(&__cgofn__cgo_506f45f9fa85_Cfunc_sum) 38 | 39 | //go:cgo_unsafe_args 40 | func _Cfunc_sum(p0 _Ctype_int, p1 _Ctype_int) (r1 _Ctype_int) { 41 | _cgo_runtime_cgocall(_cgo_506f45f9fa85_Cfunc_sum, uintptr(unsafe.Pointer(&p0))) 42 | if _Cgo_always_false { 43 | _Cgo_use(p0) 44 | _Cgo_use(p1) 45 | } 46 | return 47 | } 48 | -------------------------------------------------------------------------------- /examples/ch2-05-internal/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-05-internal/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-05-internal/02-go-call-c-func/_obj/main.cgo2.c: -------------------------------------------------------------------------------- 1 | 2 | #line 1 "cgo-builtin-prolog" 3 | #include /* for ptrdiff_t and size_t below */ 4 | 5 | /* Define intgo when compiling with GCC. */ 6 | typedef ptrdiff_t intgo; 7 | 8 | typedef struct { const char *p; intgo n; } _GoString_; 9 | typedef struct { char *p; intgo n; intgo c; } _GoBytes_; 10 | _GoString_ GoString(char *p); 11 | _GoString_ GoStringN(char *p, int l); 12 | _GoBytes_ GoBytes(void *p, int n); 13 | char *CString(_GoString_); 14 | void *CBytes(_GoBytes_); 15 | void *_CMalloc(size_t); 16 | 17 | __attribute__ ((unused)) 18 | static size_t _GoStringLen(_GoString_ s) { return s.n; } 19 | 20 | __attribute__ ((unused)) 21 | static const char *_GoStringPtr(_GoString_ s) { return s.p; } 22 | 23 | #line 6 "/Users/chai/go/src/github.com/chai2010/advanced-go-programming-book/examples/ch2-05-internal/02-go-call-c-func/main.go" 24 | int sum(int a, int b) { return a+b; } 25 | 26 | #line 1 "cgo-generated-wrapper" 27 | 28 | 29 | #line 1 "cgo-gcc-prolog" 30 | /* 31 | If x and y are not equal, the type will be invalid 32 | (have a negative array count) and an inscrutable error will come 33 | out of the compiler and hopefully mention "name". 34 | */ 35 | #define __cgo_compile_assert_eq(x, y, name) typedef char name[(x-y)*(x-y)*-2+1]; 36 | 37 | /* Check at compile time that the sizes we use match our expectations. */ 38 | #define __cgo_size_assert(t, n) __cgo_compile_assert_eq(sizeof(t), n, _cgo_sizeof_##t##_is_not_##n) 39 | 40 | __cgo_size_assert(char, 1) 41 | __cgo_size_assert(short, 2) 42 | __cgo_size_assert(int, 4) 43 | typedef long long __cgo_long_long; 44 | __cgo_size_assert(__cgo_long_long, 8) 45 | __cgo_size_assert(float, 4) 46 | __cgo_size_assert(double, 8) 47 | 48 | extern char* _cgo_topofstack(void); 49 | 50 | #include 51 | #include 52 | 53 | 54 | #define CGO_NO_SANITIZE_THREAD 55 | #define _cgo_tsan_acquire() 56 | #define _cgo_tsan_release() 57 | 58 | CGO_NO_SANITIZE_THREAD 59 | void 60 | _cgo_506f45f9fa85_Cfunc_sum(void *v) 61 | { 62 | struct { 63 | int p0; 64 | int p1; 65 | int r; 66 | char __pad12[4]; 67 | } __attribute__((__packed__)) *a = v; 68 | char *stktop = _cgo_topofstack(); 69 | __typeof__(a->r) r; 70 | _cgo_tsan_acquire(); 71 | r = sum(a->p0, a->p1); 72 | _cgo_tsan_release(); 73 | a = (void*)((char*)a + (_cgo_topofstack() - stktop)); 74 | a->r = r; 75 | } 76 | 77 | -------------------------------------------------------------------------------- /examples/ch2-05-internal/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-05-internal/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-05-internal/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-05-internal/03-c-call-go-func/_obj/_cgo_export.h: -------------------------------------------------------------------------------- 1 | /* Created by "go tool cgo" - DO NOT EDIT. */ 2 | 3 | /* package main */ 4 | 5 | 6 | #line 1 "cgo-builtin-prolog" 7 | 8 | #include /* for ptrdiff_t below */ 9 | 10 | #ifndef GO_CGO_EXPORT_PROLOGUE_H 11 | #define GO_CGO_EXPORT_PROLOGUE_H 12 | 13 | typedef struct { const char *p; ptrdiff_t n; } _GoString_; 14 | 15 | #endif 16 | 17 | /* Start of preamble from import "C" comments. */ 18 | 19 | 20 | #line 6 "/Users/chai/go/src/github.com/chai2010/advanced-go-programming-book/examples/ch2-05-internal/03-c-call-go-func/sum.go" 21 | int sum(int a, int b); 22 | 23 | #line 1 "cgo-generated-wrapper" 24 | 25 | 26 | /* End of preamble from import "C" comments. */ 27 | 28 | 29 | /* Start of boilerplate cgo prologue. */ 30 | #line 1 "cgo-gcc-export-header-prolog" 31 | 32 | #ifndef GO_CGO_PROLOGUE_H 33 | #define GO_CGO_PROLOGUE_H 34 | 35 | typedef signed char GoInt8; 36 | typedef unsigned char GoUint8; 37 | typedef short GoInt16; 38 | typedef unsigned short GoUint16; 39 | typedef int GoInt32; 40 | typedef unsigned int GoUint32; 41 | typedef long long GoInt64; 42 | typedef unsigned long long GoUint64; 43 | typedef GoInt64 GoInt; 44 | typedef GoUint64 GoUint; 45 | typedef __SIZE_TYPE__ GoUintptr; 46 | typedef float GoFloat32; 47 | typedef double GoFloat64; 48 | typedef float _Complex GoComplex64; 49 | typedef double _Complex GoComplex128; 50 | 51 | /* 52 | static assertion to make sure the file is being used on architecture 53 | at least with matching size of GoInt. 54 | */ 55 | typedef char _check_for_64_bit_pointer_matching_GoInt[sizeof(void*)==64/8 ? 1:-1]; 56 | 57 | typedef _GoString_ GoString; 58 | typedef void *GoMap; 59 | typedef void *GoChan; 60 | typedef struct { void *t; void *v; } GoInterface; 61 | typedef struct { void *data; GoInt len; GoInt cap; } GoSlice; 62 | 63 | #endif 64 | 65 | /* End of boilerplate cgo prologue. */ 66 | 67 | #ifdef __cplusplus 68 | extern "C" { 69 | #endif 70 | 71 | 72 | extern int sum(int p0, int p1); 73 | 74 | #ifdef __cplusplus 75 | } 76 | #endif 77 | -------------------------------------------------------------------------------- /examples/ch2-05-internal/03-c-call-go-func/_obj/_cgo_flags: -------------------------------------------------------------------------------- 1 | _CGO_CFLAGS= 2 | -------------------------------------------------------------------------------- /examples/ch2-05-internal/03-c-call-go-func/_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_int int32 19 | 20 | type _Ctype_void [0]byte 21 | 22 | //go:linkname _cgo_runtime_cgocall runtime.cgocall 23 | func _cgo_runtime_cgocall(unsafe.Pointer, uintptr) int32 24 | 25 | //go:linkname _cgo_runtime_cgocallback runtime.cgocallback 26 | func _cgo_runtime_cgocallback(unsafe.Pointer, unsafe.Pointer, uintptr, uintptr) 27 | 28 | //go:linkname _cgoCheckPointer runtime.cgoCheckPointer 29 | func _cgoCheckPointer(interface{}, ...interface{}) 30 | 31 | //go:linkname _cgoCheckResult runtime.cgoCheckResult 32 | func _cgoCheckResult(interface{}) 33 | 34 | //go:cgo_export_dynamic sum 35 | //go:linkname _cgoexp_8313eaf44386_sum _cgoexp_8313eaf44386_sum 36 | //go:cgo_export_static _cgoexp_8313eaf44386_sum 37 | //go:nosplit 38 | //go:norace 39 | func _cgoexp_8313eaf44386_sum(a unsafe.Pointer, n int32, ctxt uintptr) { 40 | fn := _cgoexpwrap_8313eaf44386_sum 41 | _cgo_runtime_cgocallback(**(**unsafe.Pointer)(unsafe.Pointer(&fn)), a, uintptr(n), ctxt); 42 | } 43 | 44 | func _cgoexpwrap_8313eaf44386_sum(p0 _Ctype_int, p1 _Ctype_int) (r0 _Ctype_int) { 45 | return sum(p0, p1) 46 | } 47 | -------------------------------------------------------------------------------- /examples/ch2-05-internal/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-05-internal/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-05-internal/03-c-call-go-func/_obj/sum.cgo2.c: -------------------------------------------------------------------------------- 1 | 2 | #line 1 "cgo-builtin-prolog" 3 | #include /* for ptrdiff_t and size_t below */ 4 | 5 | /* Define intgo when compiling with GCC. */ 6 | typedef ptrdiff_t intgo; 7 | 8 | typedef struct { const char *p; intgo n; } _GoString_; 9 | typedef struct { char *p; intgo n; intgo c; } _GoBytes_; 10 | _GoString_ GoString(char *p); 11 | _GoString_ GoStringN(char *p, int l); 12 | _GoBytes_ GoBytes(void *p, int n); 13 | char *CString(_GoString_); 14 | void *CBytes(_GoBytes_); 15 | void *_CMalloc(size_t); 16 | 17 | __attribute__ ((unused)) 18 | static size_t _GoStringLen(_GoString_ s) { return s.n; } 19 | 20 | __attribute__ ((unused)) 21 | static const char *_GoStringPtr(_GoString_ s) { return s.p; } 22 | 23 | #line 6 "/Users/chai/go/src/github.com/chai2010/advanced-go-programming-book/examples/ch2-05-internal/03-c-call-go-func/sum.go" 24 | int sum(int a, int b); 25 | 26 | #line 1 "cgo-generated-wrapper" 27 | 28 | 29 | #line 1 "cgo-gcc-prolog" 30 | /* 31 | If x and y are not equal, the type will be invalid 32 | (have a negative array count) and an inscrutable error will come 33 | out of the compiler and hopefully mention "name". 34 | */ 35 | #define __cgo_compile_assert_eq(x, y, name) typedef char name[(x-y)*(x-y)*-2+1]; 36 | 37 | /* Check at compile time that the sizes we use match our expectations. */ 38 | #define __cgo_size_assert(t, n) __cgo_compile_assert_eq(sizeof(t), n, _cgo_sizeof_##t##_is_not_##n) 39 | 40 | __cgo_size_assert(char, 1) 41 | __cgo_size_assert(short, 2) 42 | __cgo_size_assert(int, 4) 43 | typedef long long __cgo_long_long; 44 | __cgo_size_assert(__cgo_long_long, 8) 45 | __cgo_size_assert(float, 4) 46 | __cgo_size_assert(double, 8) 47 | 48 | extern char* _cgo_topofstack(void); 49 | 50 | #include 51 | #include 52 | 53 | 54 | #define CGO_NO_SANITIZE_THREAD 55 | #define _cgo_tsan_acquire() 56 | #define _cgo_tsan_release() 57 | 58 | -------------------------------------------------------------------------------- /examples/ch2-05-internal/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-05-internal/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-05-internal/03-c-call-go-func/sum.h: -------------------------------------------------------------------------------- 1 | /* Created by "go tool cgo" - DO NOT EDIT. */ 2 | 3 | /* package command-line-arguments */ 4 | 5 | 6 | #line 1 "cgo-builtin-prolog" 7 | 8 | #include /* for ptrdiff_t below */ 9 | 10 | #ifndef GO_CGO_EXPORT_PROLOGUE_H 11 | #define GO_CGO_EXPORT_PROLOGUE_H 12 | 13 | typedef struct { const char *p; ptrdiff_t n; } _GoString_; 14 | 15 | #endif 16 | 17 | /* Start of preamble from import "C" comments. */ 18 | 19 | 20 | #line 6 "/Users/chai/go/src/github.com/chai2010/advanced-go-programming-book/examples/ch2-05-internal/03-c-call-go-func/sum.go" 21 | int sum(int a, int b); 22 | 23 | #line 1 "cgo-generated-wrapper" 24 | 25 | 26 | /* End of preamble from import "C" comments. */ 27 | 28 | 29 | /* Start of boilerplate cgo prologue. */ 30 | #line 1 "cgo-gcc-export-header-prolog" 31 | 32 | #ifndef GO_CGO_PROLOGUE_H 33 | #define GO_CGO_PROLOGUE_H 34 | 35 | typedef signed char GoInt8; 36 | typedef unsigned char GoUint8; 37 | typedef short GoInt16; 38 | typedef unsigned short GoUint16; 39 | typedef int GoInt32; 40 | typedef unsigned int GoUint32; 41 | typedef long long GoInt64; 42 | typedef unsigned long long GoUint64; 43 | typedef GoInt64 GoInt; 44 | typedef GoUint64 GoUint; 45 | typedef __SIZE_TYPE__ GoUintptr; 46 | typedef float GoFloat32; 47 | typedef double GoFloat64; 48 | typedef float _Complex GoComplex64; 49 | typedef double _Complex GoComplex128; 50 | 51 | /* 52 | static assertion to make sure the file is being used on architecture 53 | at least with matching size of GoInt. 54 | */ 55 | typedef char _check_for_64_bit_pointer_matching_GoInt[sizeof(void*)==64/8 ? 1:-1]; 56 | 57 | typedef _GoString_ GoString; 58 | typedef void *GoMap; 59 | typedef void *GoChan; 60 | typedef struct { void *t; void *v; } GoInterface; 61 | typedef struct { void *data; GoInt len; GoInt cap; } GoSlice; 62 | 63 | #endif 64 | 65 | /* End of boilerplate cgo prologue. */ 66 | 67 | #ifdef __cplusplus 68 | extern "C" { 69 | #endif 70 | 71 | 72 | extern int sum(int p0, int p1); 73 | 74 | #ifdef __cplusplus 75 | } 76 | #endif 77 | -------------------------------------------------------------------------------- /examples/ch2-06-qsort/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-06-qsort/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-06-qsort/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-06-qsort/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-06-qsort/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-06-qsort/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-06-qsort/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-06-qsort/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-06-qsort/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-06-qsort/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-06-qsort/04-qsort-v4/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 | 11 | extern int _cgo_qsort_compare(void* a, void* b); 12 | */ 13 | import "C" 14 | 15 | import ( 16 | "fmt" 17 | "reflect" 18 | "sync" 19 | "unsafe" 20 | ) 21 | 22 | var go_qsort_compare_info struct { 23 | base unsafe.Pointer 24 | elemnum int 25 | elemsize int 26 | less func(a, b int) bool 27 | sync.Mutex 28 | } 29 | 30 | //export _cgo_qsort_compare 31 | func _cgo_qsort_compare(a, b unsafe.Pointer) C.int { 32 | var ( 33 | // array memory is locked 34 | base = uintptr(go_qsort_compare_info.base) 35 | elemsize = uintptr(go_qsort_compare_info.elemsize) 36 | ) 37 | 38 | i := int((uintptr(a) - base) / elemsize) 39 | j := int((uintptr(b) - base) / elemsize) 40 | 41 | switch { 42 | case go_qsort_compare_info.less(i, j): // v[i] < v[j] 43 | return -1 44 | case go_qsort_compare_info.less(j, i): // v[i] > v[j] 45 | return +1 46 | default: 47 | return 0 48 | } 49 | } 50 | 51 | func Slice(slice interface{}, less func(a, b int) bool) { 52 | sv := reflect.ValueOf(slice) 53 | if sv.Kind() != reflect.Slice { 54 | panic(fmt.Sprintf("qsort called with non-slice value of type %T", slice)) 55 | } 56 | if sv.Len() == 0 { 57 | return 58 | } 59 | 60 | go_qsort_compare_info.Lock() 61 | defer go_qsort_compare_info.Unlock() 62 | 63 | defer func() { 64 | go_qsort_compare_info.base = nil 65 | go_qsort_compare_info.elemnum = 0 66 | go_qsort_compare_info.elemsize = 0 67 | go_qsort_compare_info.less = nil 68 | }() 69 | 70 | // baseMem = unsafe.Pointer(sv.Index(0).Addr().Pointer()) 71 | // baseMem maybe moved, so must saved after call C.fn 72 | go_qsort_compare_info.base = unsafe.Pointer(sv.Index(0).Addr().Pointer()) 73 | go_qsort_compare_info.elemnum = sv.Len() 74 | go_qsort_compare_info.elemsize = int(sv.Type().Elem().Size()) 75 | go_qsort_compare_info.less = less 76 | 77 | C.qsort( 78 | go_qsort_compare_info.base, 79 | C.size_t(go_qsort_compare_info.elemnum), 80 | C.size_t(go_qsort_compare_info.elemsize), 81 | C.qsort_cmp_func_t(C._cgo_qsort_compare), 82 | ) 83 | } 84 | -------------------------------------------------------------------------------- /examples/ch2-06-qsort/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-08-class/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-08-class/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-08-class/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-08-class/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-08-class/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-08-class/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-08-class/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-08-class/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-08-class/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-08-class/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-08-class/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-08-class/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-08-class/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-08-class/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-08-class/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-09-so-and-lib/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-09-so-and-lib/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-09-so-and-lib/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-09-so-and-lib/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-09-so-and-lib/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-09-so-and-lib/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-09-so-and-lib/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-09-so-and-lib/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-09-so-and-lib/make-clib-dll/number-win64.def: -------------------------------------------------------------------------------- 1 | LIBRARY number-win64.dll 2 | 3 | EXPORTS 4 | number_add_mod 5 | -------------------------------------------------------------------------------- /examples/ch2-09-so-and-lib/make-clib-dll/number.h: -------------------------------------------------------------------------------- 1 | /* Created by "go tool cgo" - DO NOT EDIT. */ 2 | 3 | /* package github.com/chai2010/advanced-go-programming-book/examples/ch2-06/make-clib-dll */ 4 | 5 | /* Start of preamble from import "C" comments. */ 6 | 7 | 8 | 9 | 10 | /* End of preamble from import "C" comments. */ 11 | 12 | 13 | /* Start of boilerplate cgo prologue. */ 14 | #line 1 "cgo-gcc-export-header-prolog" 15 | 16 | #ifndef GO_CGO_PROLOGUE_H 17 | #define GO_CGO_PROLOGUE_H 18 | 19 | typedef signed char GoInt8; 20 | typedef unsigned char GoUint8; 21 | typedef short GoInt16; 22 | typedef unsigned short GoUint16; 23 | typedef int GoInt32; 24 | typedef unsigned int GoUint32; 25 | typedef long long GoInt64; 26 | typedef unsigned long long GoUint64; 27 | typedef GoInt64 GoInt; 28 | typedef GoUint64 GoUint; 29 | typedef __SIZE_TYPE__ GoUintptr; 30 | typedef float GoFloat32; 31 | typedef double GoFloat64; 32 | typedef float _Complex GoComplex64; 33 | typedef double _Complex GoComplex128; 34 | 35 | /* 36 | static assertion to make sure the file is being used on architecture 37 | at least with matching size of GoInt. 38 | */ 39 | typedef char _check_for_64_bit_pointer_matching_GoInt[sizeof(void*)==64/8 ? 1:-1]; 40 | 41 | typedef struct { const char *p; GoInt n; } GoString; 42 | typedef void *GoMap; 43 | typedef void *GoChan; 44 | typedef struct { void *t; void *v; } GoInterface; 45 | typedef struct { void *data; GoInt len; GoInt cap; } GoSlice; 46 | 47 | #endif 48 | 49 | /* End of boilerplate cgo prologue. */ 50 | 51 | #ifdef __cplusplus 52 | extern "C" { 53 | #endif 54 | 55 | 56 | extern int number_add_mod(int p0, int p1, int p2); 57 | 58 | #ifdef __cplusplus 59 | } 60 | #endif 61 | -------------------------------------------------------------------------------- /examples/ch2-09-so-and-lib/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-09-so-and-lib/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-09-so-and-lib/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 | _ "github.com/chai2010/advanced-go-programming-book/examples/ch2-06/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-09-so-and-lib/make-clib-from-multi-pkg/main.h: -------------------------------------------------------------------------------- 1 | /* Created by "go tool cgo" - DO NOT EDIT. */ 2 | 3 | /* package github.com/chai2010/advanced-go-programming-book/examples/ch2-06/make-clib-from-multi-pkg */ 4 | 5 | /* Start of preamble from import "C" comments. */ 6 | 7 | 8 | 9 | 10 | /* End of preamble from import "C" comments. */ 11 | 12 | 13 | /* Start of boilerplate cgo prologue. */ 14 | #line 1 "cgo-gcc-export-header-prolog" 15 | 16 | #ifndef GO_CGO_PROLOGUE_H 17 | #define GO_CGO_PROLOGUE_H 18 | 19 | typedef signed char GoInt8; 20 | typedef unsigned char GoUint8; 21 | typedef short GoInt16; 22 | typedef unsigned short GoUint16; 23 | typedef int GoInt32; 24 | typedef unsigned int GoUint32; 25 | typedef long long GoInt64; 26 | typedef unsigned long long GoUint64; 27 | typedef GoInt64 GoInt; 28 | typedef GoUint64 GoUint; 29 | typedef __SIZE_TYPE__ GoUintptr; 30 | typedef float GoFloat32; 31 | typedef double GoFloat64; 32 | typedef float _Complex GoComplex64; 33 | typedef double _Complex GoComplex128; 34 | 35 | /* 36 | static assertion to make sure the file is being used on architecture 37 | at least with matching size of GoInt. 38 | */ 39 | typedef char _check_for_64_bit_pointer_matching_GoInt[sizeof(void*)==64/8 ? 1:-1]; 40 | 41 | typedef struct { const char *p; GoInt n; } GoString; 42 | typedef void *GoMap; 43 | typedef void *GoChan; 44 | typedef struct { void *t; void *v; } GoInterface; 45 | typedef struct { void *data; GoInt len; GoInt cap; } GoSlice; 46 | 47 | #endif 48 | 49 | /* End of boilerplate cgo prologue. */ 50 | 51 | #ifdef __cplusplus 52 | extern "C" { 53 | #endif 54 | 55 | 56 | extern void goPrintln(char* p0); 57 | 58 | #ifdef __cplusplus 59 | } 60 | #endif 61 | -------------------------------------------------------------------------------- /examples/ch2-09-so-and-lib/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-09-so-and-lib/make-clib-from-multi-pkg/number/number.h: -------------------------------------------------------------------------------- 1 | int number_add_mod(int a, int b, int mod); 2 | -------------------------------------------------------------------------------- /examples/ch2-09-so-and-lib/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-09-so-and-lib/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-09-so-and-lib/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-09-so-and-lib/make-clib-shared/number.h: -------------------------------------------------------------------------------- 1 | /* Created by "go tool cgo" - DO NOT EDIT. */ 2 | 3 | /* package github.com/chai2010/advanced-go-programming-book/examples/ch2-06/make-clib-shared */ 4 | 5 | /* Start of preamble from import "C" comments. */ 6 | 7 | 8 | 9 | 10 | /* End of preamble from import "C" comments. */ 11 | 12 | 13 | /* Start of boilerplate cgo prologue. */ 14 | #line 1 "cgo-gcc-export-header-prolog" 15 | 16 | #ifndef GO_CGO_PROLOGUE_H 17 | #define GO_CGO_PROLOGUE_H 18 | 19 | typedef signed char GoInt8; 20 | typedef unsigned char GoUint8; 21 | typedef short GoInt16; 22 | typedef unsigned short GoUint16; 23 | typedef int GoInt32; 24 | typedef unsigned int GoUint32; 25 | typedef long long GoInt64; 26 | typedef unsigned long long GoUint64; 27 | typedef GoInt64 GoInt; 28 | typedef GoUint64 GoUint; 29 | typedef __SIZE_TYPE__ GoUintptr; 30 | typedef float GoFloat32; 31 | typedef double GoFloat64; 32 | typedef float _Complex GoComplex64; 33 | typedef double _Complex GoComplex128; 34 | 35 | /* 36 | static assertion to make sure the file is being used on architecture 37 | at least with matching size of GoInt. 38 | */ 39 | typedef char _check_for_64_bit_pointer_matching_GoInt[sizeof(void*)==64/8 ? 1:-1]; 40 | 41 | typedef struct { const char *p; GoInt n; } GoString; 42 | typedef void *GoMap; 43 | typedef void *GoChan; 44 | typedef struct { void *t; void *v; } GoInterface; 45 | typedef struct { void *data; GoInt len; GoInt cap; } GoSlice; 46 | 47 | #endif 48 | 49 | /* End of boilerplate cgo prologue. */ 50 | 51 | #ifdef __cplusplus 52 | extern "C" { 53 | #endif 54 | 55 | 56 | extern int number_add_mod(int p0, int p1, int p2); 57 | 58 | #ifdef __cplusplus 59 | } 60 | #endif 61 | -------------------------------------------------------------------------------- /examples/ch2-09-so-and-lib/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-09-so-and-lib/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-09-so-and-lib/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-09-so-and-lib/make-clib-static/number.h: -------------------------------------------------------------------------------- 1 | /* Created by "go tool cgo" - DO NOT EDIT. */ 2 | 3 | /* package github.com/chai2010/advanced-go-programming-book/examples/ch2-06/use-clib-static */ 4 | 5 | /* Start of preamble from import "C" comments. */ 6 | 7 | 8 | 9 | 10 | /* End of preamble from import "C" comments. */ 11 | 12 | 13 | /* Start of boilerplate cgo prologue. */ 14 | #line 1 "cgo-gcc-export-header-prolog" 15 | 16 | #ifndef GO_CGO_PROLOGUE_H 17 | #define GO_CGO_PROLOGUE_H 18 | 19 | typedef signed char GoInt8; 20 | typedef unsigned char GoUint8; 21 | typedef short GoInt16; 22 | typedef unsigned short GoUint16; 23 | typedef int GoInt32; 24 | typedef unsigned int GoUint32; 25 | typedef long long GoInt64; 26 | typedef unsigned long long GoUint64; 27 | typedef GoInt64 GoInt; 28 | typedef GoUint64 GoUint; 29 | typedef __SIZE_TYPE__ GoUintptr; 30 | typedef float GoFloat32; 31 | typedef double GoFloat64; 32 | typedef float _Complex GoComplex64; 33 | typedef double _Complex GoComplex128; 34 | 35 | /* 36 | static assertion to make sure the file is being used on architecture 37 | at least with matching size of GoInt. 38 | */ 39 | typedef char _check_for_64_bit_pointer_matching_GoInt[sizeof(void*)==64/8 ? 1:-1]; 40 | 41 | typedef struct { const char *p; GoInt n; } GoString; 42 | typedef void *GoMap; 43 | typedef void *GoChan; 44 | typedef struct { void *t; void *v; } GoInterface; 45 | typedef struct { void *data; GoInt len; GoInt cap; } GoSlice; 46 | 47 | #endif 48 | 49 | /* End of boilerplate cgo prologue. */ 50 | 51 | #ifdef __cplusplus 52 | extern "C" { 53 | #endif 54 | 55 | 56 | extern int number_add_mod(int p0, int p1, int p2); 57 | 58 | #ifdef __cplusplus 59 | } 60 | #endif 61 | -------------------------------------------------------------------------------- /examples/ch2-09-so-and-lib/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-09-so-and-lib/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-09-so-and-lib/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-09-so-and-lib/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-09-so-and-lib/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-09-so-and-lib/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-09-so-and-lib/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-09-so-and-lib/use-clib-shared/number/number.h: -------------------------------------------------------------------------------- 1 | int number_add_mod(int a, int b, int mod); 2 | -------------------------------------------------------------------------------- /examples/ch2-09-so-and-lib/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-09-so-and-lib/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-09-so-and-lib/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-09-so-and-lib/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-09-so-and-lib/use-clib-static-v1/number/number.h: -------------------------------------------------------------------------------- 1 | int number_add_mod(int a, int b, int mod); 2 | -------------------------------------------------------------------------------- /examples/ch2-09-so-and-lib/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-09-so-and-lib/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-09-so-and-lib/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-09-so-and-lib/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-09-so-and-lib/use-clib-static-v2/number/number.h: -------------------------------------------------------------------------------- 1 | int number_add_mod(int a, int b, int mod); 2 | -------------------------------------------------------------------------------- /examples/ch2-09-so-and-lib/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-10-py/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-py/hello-py/gopkg.h: -------------------------------------------------------------------------------- 1 | /* Created by "go tool cgo" - DO NOT EDIT. */ 2 | 3 | /* package command-line-arguments */ 4 | 5 | /* Start of preamble from import "C" comments. */ 6 | 7 | 8 | #line 6 "/Users/chai/go/src/github.com/chai2010/advanced-go-programming-book/examples/ch2-07/hello-py/main.go" 9 | 10 | // macOS: 11 | 12 | 13 | // linux 14 | 15 | 16 | // windows 17 | // should generate libpython3.a from python3.lib 18 | 19 | #define Py_LIMITED_API 20 | #include 21 | 22 | extern PyObject* PyInit_gopkg(); 23 | extern PyObject* Py_gopkg_sum(PyObject *, PyObject *); 24 | 25 | static int cgo_PyArg_ParseTuple_ii(PyObject *arg, int *a, int *b) { 26 | return PyArg_ParseTuple(arg, "ii", a, b); 27 | } 28 | 29 | static PyObject* cgo_PyInit_gopkg(void) { 30 | static PyMethodDef methods[] = { 31 | {"sum", Py_gopkg_sum, METH_VARARGS, "Add two numbers."}, 32 | {NULL, NULL, 0, NULL}, 33 | }; 34 | static struct PyModuleDef module = { 35 | PyModuleDef_HEAD_INIT, "gopkg", NULL, -1, methods, 36 | }; 37 | return PyModule_Create(&module); 38 | } 39 | 40 | #line 1 "cgo-generated-wrapper" 41 | 42 | 43 | /* End of preamble from import "C" comments. */ 44 | 45 | 46 | /* Start of boilerplate cgo prologue. */ 47 | #line 1 "cgo-gcc-export-header-prolog" 48 | 49 | #ifndef GO_CGO_PROLOGUE_H 50 | #define GO_CGO_PROLOGUE_H 51 | 52 | typedef signed char GoInt8; 53 | typedef unsigned char GoUint8; 54 | typedef short GoInt16; 55 | typedef unsigned short GoUint16; 56 | typedef int GoInt32; 57 | typedef unsigned int GoUint32; 58 | typedef long long GoInt64; 59 | typedef unsigned long long GoUint64; 60 | typedef GoInt64 GoInt; 61 | typedef GoUint64 GoUint; 62 | typedef __SIZE_TYPE__ GoUintptr; 63 | typedef float GoFloat32; 64 | typedef double GoFloat64; 65 | typedef float _Complex GoComplex64; 66 | typedef double _Complex GoComplex128; 67 | 68 | /* 69 | static assertion to make sure the file is being used on architecture 70 | at least with matching size of GoInt. 71 | */ 72 | typedef char _check_for_64_bit_pointer_matching_GoInt[sizeof(void*)==64/8 ? 1:-1]; 73 | 74 | typedef struct { const char *p; GoInt n; } GoString; 75 | typedef void *GoMap; 76 | typedef void *GoChan; 77 | typedef struct { void *t; void *v; } GoInterface; 78 | typedef struct { void *data; GoInt len; GoInt cap; } GoSlice; 79 | 80 | #endif 81 | 82 | /* End of boilerplate cgo prologue. */ 83 | 84 | #ifdef __cplusplus 85 | extern "C" { 86 | #endif 87 | 88 | 89 | extern PyObject* PyInit_gopkg(); 90 | 91 | extern PyObject* Py_gopkg_sum(PyObject* p0, PyObject* p1); 92 | 93 | #ifdef __cplusplus 94 | } 95 | #endif 96 | -------------------------------------------------------------------------------- /examples/ch2-10-py/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-py/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-py/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-py/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-py/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-py/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-10-py/hello-so/say-hello.h: -------------------------------------------------------------------------------- 1 | /* Created by "go tool cgo" - DO NOT EDIT. */ 2 | 3 | /* package command-line-arguments */ 4 | 5 | /* Start of preamble from import "C" comments. */ 6 | 7 | 8 | 9 | 10 | /* End of preamble from import "C" comments. */ 11 | 12 | 13 | /* Start of boilerplate cgo prologue. */ 14 | #line 1 "cgo-gcc-export-header-prolog" 15 | 16 | #ifndef GO_CGO_PROLOGUE_H 17 | #define GO_CGO_PROLOGUE_H 18 | 19 | typedef signed char GoInt8; 20 | typedef unsigned char GoUint8; 21 | typedef short GoInt16; 22 | typedef unsigned short GoUint16; 23 | typedef int GoInt32; 24 | typedef unsigned int GoUint32; 25 | typedef long long GoInt64; 26 | typedef unsigned long long GoUint64; 27 | typedef GoInt64 GoInt; 28 | typedef GoUint64 GoUint; 29 | typedef __SIZE_TYPE__ GoUintptr; 30 | typedef float GoFloat32; 31 | typedef double GoFloat64; 32 | typedef float _Complex GoComplex64; 33 | typedef double _Complex GoComplex128; 34 | 35 | /* 36 | static assertion to make sure the file is being used on architecture 37 | at least with matching size of GoInt. 38 | */ 39 | typedef char _check_for_64_bit_pointer_matching_GoInt[sizeof(void*)==64/8 ? 1:-1]; 40 | 41 | typedef struct { const char *p; GoInt n; } GoString; 42 | typedef void *GoMap; 43 | typedef void *GoChan; 44 | typedef struct { void *t; void *v; } GoInterface; 45 | typedef struct { void *data; GoInt len; GoInt cap; } GoSlice; 46 | 47 | #endif 48 | 49 | /* End of boilerplate cgo prologue. */ 50 | 51 | #ifdef __cplusplus 52 | extern "C" { 53 | #endif 54 | 55 | 56 | extern void SayHello(char* p0); 57 | 58 | #ifdef __cplusplus 59 | } 60 | #endif 61 | -------------------------------------------------------------------------------- /examples/ch2-xx-08/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-xx-08/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-xx-08/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-xx-08/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-xx-08/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-xx-08/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-xx-08/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-xx-08/hello-swig-v2/hello.go: -------------------------------------------------------------------------------- 1 | /* ---------------------------------------------------------------------------- 2 | * This file was automatically generated by SWIG (http://www.swig.org). 3 | * Version 3.0.12 4 | * 5 | * This file is not intended to be easily readable and contains a number of 6 | * coding conventions designed to improve portability and efficiency. Do not make 7 | * changes to this file unless you know what you are doing--modify the SWIG 8 | * interface file instead. 9 | * ----------------------------------------------------------------------------- */ 10 | 11 | // source: hello.i 12 | 13 | package hello 14 | 15 | /* 16 | #define intgo swig_intgo 17 | typedef void *swig_voidp; 18 | 19 | #include 20 | 21 | 22 | typedef long long intgo; 23 | typedef unsigned long long uintgo; 24 | 25 | 26 | 27 | typedef struct { char *p; intgo n; } _gostring_; 28 | typedef struct { void* array; intgo len; intgo cap; } _goslice_; 29 | 30 | 31 | extern void _wrap_Swig_free_hello_679051ef4cde42b8(uintptr_t arg1); 32 | extern uintptr_t _wrap_Swig_malloc_hello_679051ef4cde42b8(swig_intgo arg1); 33 | extern void _wrap_SayHello_hello_679051ef4cde42b8(void); 34 | #undef intgo 35 | */ 36 | import "C" 37 | 38 | import "unsafe" 39 | import _ "runtime/cgo" 40 | import "sync" 41 | 42 | 43 | type _ unsafe.Pointer 44 | 45 | 46 | 47 | var Swig_escape_always_false bool 48 | var Swig_escape_val interface{} 49 | 50 | 51 | type _swig_fnptr *byte 52 | type _swig_memberptr *byte 53 | 54 | 55 | type _ sync.Mutex 56 | 57 | func Swig_free(arg1 uintptr) { 58 | _swig_i_0 := arg1 59 | C._wrap_Swig_free_hello_679051ef4cde42b8(C.uintptr_t(_swig_i_0)) 60 | } 61 | 62 | func Swig_malloc(arg1 int) (_swig_ret uintptr) { 63 | var swig_r uintptr 64 | _swig_i_0 := arg1 65 | swig_r = (uintptr)(C._wrap_Swig_malloc_hello_679051ef4cde42b8(C.swig_intgo(_swig_i_0))) 66 | return swig_r 67 | } 68 | 69 | func SayHello() { 70 | C._wrap_SayHello_hello_679051ef4cde42b8() 71 | } 72 | 73 | 74 | -------------------------------------------------------------------------------- /examples/ch2-xx-08/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-xx-08/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-xx/hello/.gitignore: -------------------------------------------------------------------------------- 1 | !/_obj 2 | -------------------------------------------------------------------------------- /examples/ch2-xx/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-xx/hello/_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_16f1900c27a8_helloInt(void *, int, __SIZE_TYPE__); 15 | 16 | CGO_NO_SANITIZE_THREAD 17 | void helloInt(GoInt p0) 18 | { 19 | __SIZE_TYPE__ _cgo_ctxt = _cgo_wait_runtime_init_done(); 20 | struct { 21 | GoInt p0; 22 | } __attribute__((__packed__)) a; 23 | a.p0 = p0; 24 | _cgo_tsan_release(); 25 | crosscall2(_cgoexp_16f1900c27a8_helloInt, &a, 8, _cgo_ctxt); 26 | _cgo_tsan_acquire(); 27 | _cgo_release_context(_cgo_ctxt); 28 | } 29 | extern void _cgoexp_16f1900c27a8_helloString(void *, int, __SIZE_TYPE__); 30 | 31 | CGO_NO_SANITIZE_THREAD 32 | void helloString(GoString p0) 33 | { 34 | __SIZE_TYPE__ _cgo_ctxt = _cgo_wait_runtime_init_done(); 35 | struct { 36 | GoString p0; 37 | } __attribute__((__packed__)) a; 38 | a.p0 = p0; 39 | _cgo_tsan_release(); 40 | crosscall2(_cgoexp_16f1900c27a8_helloString, &a, 16, _cgo_ctxt); 41 | _cgo_tsan_acquire(); 42 | _cgo_release_context(_cgo_ctxt); 43 | } 44 | extern void _cgoexp_16f1900c27a8_helloSlice(void *, int, __SIZE_TYPE__); 45 | 46 | CGO_NO_SANITIZE_THREAD 47 | void helloSlice(GoSlice p0) 48 | { 49 | __SIZE_TYPE__ _cgo_ctxt = _cgo_wait_runtime_init_done(); 50 | struct { 51 | GoSlice p0; 52 | } __attribute__((__packed__)) a; 53 | a.p0 = p0; 54 | _cgo_tsan_release(); 55 | crosscall2(_cgoexp_16f1900c27a8_helloSlice, &a, 24, _cgo_ctxt); 56 | _cgo_tsan_acquire(); 57 | _cgo_release_context(_cgo_ctxt); 58 | } 59 | -------------------------------------------------------------------------------- /examples/ch2-xx/hello/_obj/_cgo_export.h: -------------------------------------------------------------------------------- 1 | /* Created by "go tool cgo" - DO NOT EDIT. */ 2 | 3 | /* package main */ 4 | 5 | /* Start of preamble from import "C" comments. */ 6 | 7 | 8 | 9 | 10 | /* End of preamble from import "C" comments. */ 11 | 12 | 13 | /* Start of boilerplate cgo prologue. */ 14 | #line 1 "cgo-gcc-export-header-prolog" 15 | 16 | #ifndef GO_CGO_PROLOGUE_H 17 | #define GO_CGO_PROLOGUE_H 18 | 19 | typedef signed char GoInt8; 20 | typedef unsigned char GoUint8; 21 | typedef short GoInt16; 22 | typedef unsigned short GoUint16; 23 | typedef int GoInt32; 24 | typedef unsigned int GoUint32; 25 | typedef long long GoInt64; 26 | typedef unsigned long long GoUint64; 27 | typedef GoInt64 GoInt; 28 | typedef GoUint64 GoUint; 29 | typedef __SIZE_TYPE__ GoUintptr; 30 | typedef float GoFloat32; 31 | typedef double GoFloat64; 32 | typedef float _Complex GoComplex64; 33 | typedef double _Complex GoComplex128; 34 | 35 | /* 36 | static assertion to make sure the file is being used on architecture 37 | at least with matching size of GoInt. 38 | */ 39 | typedef char _check_for_64_bit_pointer_matching_GoInt[sizeof(void*)==64/8 ? 1:-1]; 40 | 41 | typedef struct { const char *p; GoInt n; } GoString; 42 | typedef void *GoMap; 43 | typedef void *GoChan; 44 | typedef struct { void *t; void *v; } GoInterface; 45 | typedef struct { void *data; GoInt len; GoInt cap; } GoSlice; 46 | 47 | #endif 48 | 49 | /* End of boilerplate cgo prologue. */ 50 | 51 | #ifdef __cplusplus 52 | extern "C" { 53 | #endif 54 | 55 | 56 | extern void helloInt(GoInt p0); 57 | 58 | extern void helloString(GoString p0); 59 | 60 | extern void helloSlice(GoSlice p0); 61 | 62 | #ifdef __cplusplus 63 | } 64 | #endif 65 | -------------------------------------------------------------------------------- /examples/ch2-xx/hello/_obj/_cgo_flags: -------------------------------------------------------------------------------- 1 | _CGO_CFLAGS= 2 | -------------------------------------------------------------------------------- /examples/ch2-xx/hello/_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 | //go:cgo_export_dynamic helloInt 33 | //go:linkname _cgoexp_16f1900c27a8_helloInt _cgoexp_16f1900c27a8_helloInt 34 | //go:cgo_export_static _cgoexp_16f1900c27a8_helloInt 35 | //go:nosplit 36 | //go:norace 37 | func _cgoexp_16f1900c27a8_helloInt(a unsafe.Pointer, n int32, ctxt uintptr) { 38 | fn := _cgoexpwrap_16f1900c27a8_helloInt 39 | _cgo_runtime_cgocallback(**(**unsafe.Pointer)(unsafe.Pointer(&fn)), a, uintptr(n), ctxt); 40 | } 41 | 42 | func _cgoexpwrap_16f1900c27a8_helloInt(p0 int) { 43 | helloInt(p0) 44 | } 45 | //go:cgo_export_dynamic helloString 46 | //go:linkname _cgoexp_16f1900c27a8_helloString _cgoexp_16f1900c27a8_helloString 47 | //go:cgo_export_static _cgoexp_16f1900c27a8_helloString 48 | //go:nosplit 49 | //go:norace 50 | func _cgoexp_16f1900c27a8_helloString(a unsafe.Pointer, n int32, ctxt uintptr) { 51 | fn := _cgoexpwrap_16f1900c27a8_helloString 52 | _cgo_runtime_cgocallback(**(**unsafe.Pointer)(unsafe.Pointer(&fn)), a, uintptr(n), ctxt); 53 | } 54 | 55 | func _cgoexpwrap_16f1900c27a8_helloString(p0 string) { 56 | helloString(p0) 57 | } 58 | //go:cgo_export_dynamic helloSlice 59 | //go:linkname _cgoexp_16f1900c27a8_helloSlice _cgoexp_16f1900c27a8_helloSlice 60 | //go:cgo_export_static _cgoexp_16f1900c27a8_helloSlice 61 | //go:nosplit 62 | //go:norace 63 | func _cgoexp_16f1900c27a8_helloSlice(a unsafe.Pointer, n int32, ctxt uintptr) { 64 | fn := _cgoexpwrap_16f1900c27a8_helloSlice 65 | _cgo_runtime_cgocallback(**(**unsafe.Pointer)(unsafe.Pointer(&fn)), a, uintptr(n), ctxt); 66 | } 67 | 68 | func _cgoexpwrap_16f1900c27a8_helloSlice(p0 []byte) { 69 | helloSlice(p0) 70 | } 71 | -------------------------------------------------------------------------------- /examples/ch2-xx/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-xx/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-xx/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-xx/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-01-quick-guide/id-01/pkg.go: -------------------------------------------------------------------------------- 1 | package pkg 2 | 3 | var Id = 9527 4 | -------------------------------------------------------------------------------- /examples/ch3-01-quick-guide/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-01-quick-guide/id-02/pkg.go: -------------------------------------------------------------------------------- 1 | package pkg 2 | 3 | var Id int 4 | -------------------------------------------------------------------------------- /examples/ch3-01-quick-guide/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-01-quick-guide/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-01-quick-guide/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-01-quick-guide/main-01/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | var helloworld = "你好, 世界" 4 | 5 | func main() 6 | -------------------------------------------------------------------------------- /examples/ch3-01-quick-guide/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-01-quick-guide/str-01/pkg.go: -------------------------------------------------------------------------------- 1 | package pkg 2 | 3 | var Name = "gopher" 4 | -------------------------------------------------------------------------------- /examples/ch3-01-quick-guide/str-02/pkg.go: -------------------------------------------------------------------------------- 1 | package pkg 2 | 3 | var NameData [8]byte 4 | 5 | var Name string 6 | -------------------------------------------------------------------------------- /examples/ch3-01-quick-guide/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-01-quick-guide/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-01-quick-guide/str-03/pkg.go: -------------------------------------------------------------------------------- 1 | package pkg 2 | 3 | var NameData [8]byte 4 | 5 | var Name string 6 | -------------------------------------------------------------------------------- /examples/ch3-01-quick-guide/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-01-quick-guide/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-xx/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-xx/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-xx/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-xx/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-xx/add/add_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 add 7 | 8 | import ( 9 | "testing" 10 | ) 11 | 12 | func TestAdd(t *testing.T) { 13 | t.Run("go", func(t *testing.T) { 14 | if x := Add(1, 2); x != 3 { 15 | t.Fatalf("expect = %d, got = %d", 3, x) 16 | } 17 | }) 18 | t.Run("asm", func(t *testing.T) { 19 | if x := AsmAdd(1, 2); x != 3 { 20 | t.Fatalf("expect = %d, got = %d", 3, x) 21 | } 22 | }) 23 | } 24 | 25 | func TestAddSlice(t *testing.T) { 26 | a := []int{1, 2, 3, 4, 5} 27 | b := []int{10, 20, 30, 40, 50, 60} 28 | 29 | t.Run("go", func(t *testing.T) { 30 | x := make([]int, len(a)) 31 | AddSlice(x, a, b) 32 | 33 | for i := 0; i < len(x) && i < len(a) && i < len(b); i++ { 34 | if x[i] != a[i]+b[i] { 35 | t.Fatalf("expect = %d, got = %d", x[i], a[i]+b[i]) 36 | } 37 | } 38 | }) 39 | 40 | t.Run("asm", func(t *testing.T) { 41 | x := make([]int, len(a)) 42 | AsmAddSlice(x, a, b) 43 | 44 | for i := 0; i < len(x) && i < len(a) && i < len(b); i++ { 45 | if x[i] != a[i]+b[i] { 46 | t.Fatalf("expect = %d, got = %d", x[i], a[i]+b[i]) 47 | } 48 | } 49 | }) 50 | } 51 | 52 | func BenchmarkAdd(b *testing.B) { 53 | b.Run("go", func(b *testing.B) { 54 | for i := 0; i < b.N; i++ { 55 | Add(1, 2) 56 | } 57 | }) 58 | b.Run("asm", func(b *testing.B) { 59 | for i := 0; i < b.N; i++ { 60 | AsmAdd(1, 2) 61 | } 62 | }) 63 | } 64 | 65 | func BenchmarkAddSlice(b *testing.B) { 66 | s0 := make([]int, 10<<10) 67 | s1 := make([]int, 10<<10) 68 | dst := make([]int, 10<<10) 69 | 70 | b.Run("len=10", func(b *testing.B) { 71 | dst := dst[:10] 72 | for i := 0; i < b.N; i++ { 73 | AddSlice(dst, s0, s1) 74 | } 75 | }) 76 | b.Run("len=50", func(b *testing.B) { 77 | dst := dst[:50] 78 | for i := 0; i < b.N; i++ { 79 | AddSlice(dst, s0, s1) 80 | _ = dst 81 | } 82 | }) 83 | b.Run("len=100", func(b *testing.B) { 84 | dst := dst[:100] 85 | for i := 0; i < b.N; i++ { 86 | AddSlice(dst, s0, s1) 87 | _ = dst 88 | } 89 | }) 90 | b.Run("len=1000", func(b *testing.B) { 91 | dst := dst[:1000] 92 | for i := 0; i < b.N; i++ { 93 | AddSlice(dst, s0, s1) 94 | _ = dst 95 | } 96 | }) 97 | } 98 | -------------------------------------------------------------------------------- /examples/ch3-xx/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-xx/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-xx/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-xx/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-xx/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-xx/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-xx/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-xx/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-xx/hello/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 | // utf8: "你好, 世界!\n" 13 | // hex: e4bda0e5a5bd2c20 e4b896e7958c210a 14 | // len: 16 15 | DATA text_zh<>+0(SB)/8,$"\xe4\xbd\xa0\xe5\xa5\xbd\x2c\x20" 16 | DATA text_zh<>+8(SB)/8,$"\xe4\xb8\x96\xe7\x95\x8c\x21\x0a" 17 | GLOBL text_zh<>(SB),NOPTR,$16 18 | 19 | // func PrintHelloWorld_var() 20 | TEXT ·PrintHelloWorld_var(SB), $16-0 21 | NO_LOCAL_POINTERS 22 | CALL runtime·printlock(SB) 23 | MOVQ ·text+0(SB), AX 24 | MOVQ AX, (SP) 25 | MOVQ ·text+8(SB), AX 26 | MOVQ AX, 8(SP) 27 | CALL runtime·printstring(SB) 28 | CALL runtime·printunlock(SB) 29 | RET 30 | 31 | // func PrintHelloWorld() 32 | TEXT ·PrintHelloWorld(SB), $16-0 33 | NO_LOCAL_POINTERS 34 | CALL runtime·printlock(SB) 35 | MOVQ $text<>+0(SB), AX 36 | MOVQ AX, (SP) 37 | MOVQ $16, 8(SP) 38 | CALL runtime·printstring(SB) 39 | CALL runtime·printunlock(SB) 40 | RET 41 | 42 | // func PrintHelloWorld_zh() 43 | TEXT ·PrintHelloWorld_zh(SB), $16-0 44 | NO_LOCAL_POINTERS 45 | CALL runtime·printlock(SB) 46 | MOVQ $text_zh<>+0(SB), AX 47 | MOVQ AX, (SP) 48 | MOVQ $16, 8(SP) 49 | CALL runtime·printstring(SB) 50 | CALL runtime·printunlock(SB) 51 | RET 52 | -------------------------------------------------------------------------------- /examples/ch3-xx/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-xx/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-xx/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-xx/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-xx/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-xx/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-xx/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-xx/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-xx/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-xx/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-xx/loop/loop_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 loop 7 | 8 | import ( 9 | "testing" 10 | ) 11 | 12 | func TestLoopAdd(t *testing.T) { 13 | t.Run("go", func(t *testing.T) { 14 | if x := LoopAdd(100, 0, 1); x != 100 { 15 | t.Fatalf("expect = %d, got = %d", 100, x) 16 | } 17 | if x := LoopAdd(100, 0, 2); x != 200 { 18 | t.Fatalf("expect = %d, got = %d", 200, x) 19 | } 20 | if x := LoopAdd(100, 0, -1); x != -100 { 21 | t.Fatalf("expect = %d, got = %d", -100, x) 22 | } 23 | if x := LoopAdd(100, 50, 1); x != 150 { 24 | t.Fatalf("expect = %d, got = %d", 150, x) 25 | } 26 | }) 27 | t.Run("asm", func(t *testing.T) { 28 | if x := AsmLoopAdd(100, 0, 1); x != 100 { 29 | t.Fatalf("expect = %d, got = %d", 100, x) 30 | } 31 | if x := AsmLoopAdd(100, 0, 2); x != 200 { 32 | t.Fatalf("expect = %d, got = %d", 200, x) 33 | } 34 | if x := AsmLoopAdd(100, 0, -1); x != -100 { 35 | t.Fatalf("expect = %d, got = %d", -100, x) 36 | } 37 | if x := AsmLoopAdd(100, 50, 1); x != 150 { 38 | t.Fatalf("expect = %d, got = %d", 150, x) 39 | } 40 | }) 41 | } 42 | 43 | func BenchmarkLoopAdd(b *testing.B) { 44 | b.Run("go", func(b *testing.B) { 45 | for i := 0; i < b.N; i++ { 46 | LoopAdd(1000, 0, 1) 47 | } 48 | }) 49 | b.Run("asm", func(b *testing.B) { 50 | for i := 0; i < b.N; i++ { 51 | AsmLoopAdd(1000, 0, 1) 52 | } 53 | }) 54 | } 55 | -------------------------------------------------------------------------------- /examples/ch3-xx/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-xx/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-xx/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 | // go test -bench=. 5 | 6 | package min 7 | 8 | import ( 9 | "testing" 10 | ) 11 | 12 | func TestMin(t *testing.T) { 13 | t.Run("go", func(t *testing.T) { 14 | if x := Min(1, 2); x != 1 { 15 | t.Fatalf("expect = %d, got = %d", 1, x) 16 | } 17 | if x := Min(2, 1); x != 1 { 18 | t.Fatalf("expect = %d, got = %d", 1, x) 19 | } 20 | }) 21 | t.Run("asm", func(t *testing.T) { 22 | if x := AsmMin(1, 2); x != 1 { 23 | t.Fatalf("expect = %d, got = %d", 1, x) 24 | } 25 | if x := AsmMin(2, 1); x != 1 { 26 | t.Fatalf("expect = %d, got = %d", 1, x) 27 | } 28 | }) 29 | } 30 | func TestMax(t *testing.T) { 31 | t.Run("go", func(t *testing.T) { 32 | if x := Max(1, 2); x != 2 { 33 | t.Fatalf("expect = %d, got = %d", 2, x) 34 | } 35 | if x := Max(2, 1); x != 2 { 36 | t.Fatalf("expect = %d, got = %d", 2, x) 37 | } 38 | }) 39 | t.Run("asm", func(t *testing.T) { 40 | if x := AsmMax(1, 2); x != 2 { 41 | t.Fatalf("expect = %d, got = %d", 2, x) 42 | } 43 | if x := AsmMax(2, 1); x != 2 { 44 | t.Fatalf("expect = %d, got = %d", 2, x) 45 | } 46 | }) 47 | } 48 | 49 | func BenchmarkMin(b *testing.B) { 50 | b.Run("go", func(b *testing.B) { 51 | for i := 0; i < b.N; i++ { 52 | Min(1, 2) 53 | } 54 | }) 55 | b.Run("go.noinline", func(b *testing.B) { 56 | for i := 0; i < b.N; i++ { 57 | MinNoInline(1, 2) 58 | } 59 | }) 60 | b.Run("asm", func(b *testing.B) { 61 | for i := 0; i < b.N; i++ { 62 | AsmMin(1, 2) 63 | } 64 | }) 65 | } 66 | -------------------------------------------------------------------------------- /examples/ch3-xx/min/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("Min(1,2) =", Min(1, 2)) 14 | } 15 | -------------------------------------------------------------------------------- /examples/ch3-xx/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-xx/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-xx/slice/slice_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 AsmSumInt16Slice(v []int16) int16 7 | TEXT ·AsmSumInt16Slice(SB), NOSPLIT, $0-26 8 | MOVQ v_base+0(FP), R8 9 | MOVQ v_len+8(FP), R9 10 | SHLQ $1, R9 11 | ADDQ R8, R9 12 | MOVQ $0, R10 13 | 14 | loop: 15 | CMPQ R8, R9 16 | JE end 17 | ADDW (R8), R10 18 | ADDQ $2, R8 19 | JMP loop 20 | 21 | end: 22 | MOVW R10, ret+24(FP) 23 | RET 24 | 25 | // func AsmSumIntSlice(s []int) int 26 | TEXT ·AsmSumIntSlice(SB), NOSPLIT, $0-32 27 | MOVQ s+0(FP), AX // &s[0] 28 | MOVQ s_len+8(FP), BX // len(s) 29 | MOVQ $0, CX // sum = 0 30 | 31 | loop: 32 | CMPQ BX, $0 // compare cnt,0 33 | JLE end // if cnt <= 0: goto end 34 | DECQ BX // cnt-- 35 | ADDQ (AX), CX // sum += s[i] 36 | ADDQ $8, AX // i++ 37 | JMP loop // goto loop 38 | 39 | end: 40 | MOVQ CX, ret+24(FP) // return sum 41 | RET 42 | 43 | // func AsmSumIntSliceV2(s []int) int 44 | TEXT ·AsmSumIntSliceV2(SB), NOSPLIT, $0-32 45 | MOVQ s+0(FP), AX // p := &s[0] 46 | MOVQ s_len+8(FP), BX 47 | LEAQ 0(AX)(BX*8), BX // p_end := &s[len(s)] 48 | MOVQ $0, CX // sum = 0 49 | 50 | loop: 51 | CMPQ AX, BX // compare p,p_end 52 | JGE end // if p >= p_end: goto end 53 | ADDQ (AX), CX // sum += s[i] 54 | ADDQ $8, AX // p++ 55 | JMP loop // goto loop 56 | 57 | end: 58 | MOVQ CX, ret+24(FP) // return sum 59 | RET 60 | -------------------------------------------------------------------------------- /examples/ch3-xx/slice/slice_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 slice 7 | 8 | import ( 9 | "testing" 10 | ) 11 | 12 | func TestLoopAdd(t *testing.T) { 13 | t.Run("go", func(t *testing.T) { 14 | if x := SumIntSlice([]int{1, 2, 3}); x != 6 { 15 | t.Fatalf("expect = %d, got = %d", 6, x) 16 | } 17 | }) 18 | t.Run("asm", func(t *testing.T) { 19 | if x := AsmSumIntSlice([]int{1, 2, 3}); x != 6 { 20 | t.Fatalf("expect = %d, got = %d", 6, x) 21 | } 22 | }) 23 | t.Run("asm.v2", func(t *testing.T) { 24 | if x := AsmSumIntSliceV2([]int{1, 2, 3}); x != 6 { 25 | t.Fatalf("expect = %d, got = %d", 6, x) 26 | } 27 | }) 28 | } 29 | 30 | func BenchmarkLoopAdd(b *testing.B) { 31 | s10 := make([]int, 10) 32 | s100 := make([]int, 100) 33 | s1000 := make([]int, 1000) 34 | 35 | b.Run("go/len=10", func(b *testing.B) { 36 | for i := 0; i < b.N; i++ { 37 | SumIntSlice(s10) 38 | } 39 | }) 40 | b.Run("asm/len=10", func(b *testing.B) { 41 | for i := 0; i < b.N; i++ { 42 | AsmSumIntSlice(s10) 43 | } 44 | }) 45 | b.Run("asm.v2/len=10", func(b *testing.B) { 46 | for i := 0; i < b.N; i++ { 47 | AsmSumIntSliceV2(s10) 48 | } 49 | }) 50 | 51 | b.Run("go/len=100", func(b *testing.B) { 52 | for i := 0; i < b.N; i++ { 53 | SumIntSlice(s100) 54 | } 55 | }) 56 | b.Run("asm/len=100", func(b *testing.B) { 57 | for i := 0; i < b.N; i++ { 58 | AsmSumIntSlice(s100) 59 | } 60 | }) 61 | b.Run("asm.v2/len=100", func(b *testing.B) { 62 | for i := 0; i < b.N; i++ { 63 | AsmSumIntSliceV2(s100) 64 | } 65 | }) 66 | 67 | b.Run("go/len=1000", func(b *testing.B) { 68 | for i := 0; i < b.N; i++ { 69 | SumIntSlice(s1000) 70 | } 71 | }) 72 | b.Run("asm/len=1000", func(b *testing.B) { 73 | for i := 0; i < b.N; i++ { 74 | AsmSumIntSlice(s1000) 75 | } 76 | }) 77 | b.Run("asm.v2/len=1000", func(b *testing.B) { 78 | for i := 0; i < b.N; i++ { 79 | AsmSumIntSliceV2(s1000) 80 | } 81 | }) 82 | } 83 | -------------------------------------------------------------------------------- /examples/ch3-xx/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-xx/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-xx/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-xx/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-xx/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-xx/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-xx/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-xx/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-xx/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-xx/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 | -------------------------------------------------------------------------------- /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 | default: $(UML_PNG_FILES) $(DOT_PNG_FILES) 13 | @echo "ok" 14 | 15 | logo: 16 | convert logo-2018-01.png -resize 300x65 logo.png 17 | @echo "ok" 18 | 19 | clean: 20 | -rm *.dot.png 21 | -rm *.uml.png 22 | -rm *.uml.svg 23 | 24 | %.uml.svg: %.plantuml 25 | cat $< | docker run --rm -i chai2010/ibox:plantuml > $@ 26 | 27 | %.uml.png: %.plantuml 28 | cat $< | docker run --rm -i chai2010/ibox:plantuml -tpng > $@ 29 | 30 | %.dot.png: %.dot 31 | dot -Tpng -o $@ $< 32 | -------------------------------------------------------------------------------- /images/appendix-c-chai2010.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iikira/advanced-go-programming-book/1b5310f7547a5191d4687d94e0e6a9d32be61431/images/appendix-c-chai2010.jpg -------------------------------------------------------------------------------- /images/by-nc-sa-4.0-88x31.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iikira/advanced-go-programming-book/1b5310f7547a5191d4687d94e0e6a9d32be61431/images/by-nc-sa-4.0-88x31.png -------------------------------------------------------------------------------- /images/ch1-01-go-family-tree-x.dot: -------------------------------------------------------------------------------- 1 | digraph G { 2 | ranksep = .75; size = "7.5,7.5"; 3 | rankdir="LR"; 4 | 5 | node [shape=plaintext]; 6 | 7 | { 8 | 1970, 1972; 1985; 1989; 1992; 1995; 2007; 9 | "B"; 10 | } 11 | 12 | { 13 | node [shape=circle]; 14 | "Go"; 15 | } 16 | 17 | { rank = same; "1970"; "B"; } 18 | { rank = same; "1972"; "C"; } 19 | { rank = same; "1985"; "Squeak"; } 20 | { rank = same; "1989"; "NewSqueak"; } 21 | { rank = same; "1992"; "Alef"; } 22 | { rank = same; "1995"; "Limbo"; } 23 | { rank = same; "2007"; "Go"; } 24 | 25 | "B" -> "C" -> "Squeak" -> "NewSqueak" -> "Alef" -> "Limbo" -> "Go"; 26 | } 27 | -------------------------------------------------------------------------------- /images/ch1-01-go-family-tree-x.dot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iikira/advanced-go-programming-book/1b5310f7547a5191d4687d94e0e6a9d32be61431/images/ch1-01-go-family-tree-x.dot.png -------------------------------------------------------------------------------- /images/ch1-01-go-family-tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iikira/advanced-go-programming-book/1b5310f7547a5191d4687d94e0e6a9d32be61431/images/ch1-01-go-family-tree.png -------------------------------------------------------------------------------- /images/ch1-01-go-father.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iikira/advanced-go-programming-book/1b5310f7547a5191d4687d94e0e6a9d32be61431/images/ch1-01-go-father.jpg -------------------------------------------------------------------------------- /images/ch1-01-go-history.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iikira/advanced-go-programming-book/1b5310f7547a5191d4687d94e0e6a9d32be61431/images/ch1-01-go-history.png -------------------------------------------------------------------------------- /images/ch1-01-go-log04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iikira/advanced-go-programming-book/1b5310f7547a5191d4687d94e0e6a9d32be61431/images/ch1-01-go-log04.png -------------------------------------------------------------------------------- /images/ch1-02-alef.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iikira/advanced-go-programming-book/1b5310f7547a5191d4687d94e0e6a9d32be61431/images/ch1-02-alef.png -------------------------------------------------------------------------------- /images/ch1-02-prime-sieve.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iikira/advanced-go-programming-book/1b5310f7547a5191d4687d94e0e6a9d32be61431/images/ch1-02-prime-sieve.png -------------------------------------------------------------------------------- /images/ch1-03-array-4int.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iikira/advanced-go-programming-book/1b5310f7547a5191d4687d94e0e6a9d32be61431/images/ch1-03-array-4int.png -------------------------------------------------------------------------------- /images/ch1-03-slice-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iikira/advanced-go-programming-book/1b5310f7547a5191d4687d94e0e6a9d32be61431/images/ch1-03-slice-1.png -------------------------------------------------------------------------------- /images/ch1-03-string-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iikira/advanced-go-programming-book/1b5310f7547a5191d4687d94e0e6a9d32be61431/images/ch1-03-string-1.png -------------------------------------------------------------------------------- /images/ch1-03-string-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iikira/advanced-go-programming-book/1b5310f7547a5191d4687d94e0e6a9d32be61431/images/ch1-03-string-2.png -------------------------------------------------------------------------------- /images/ch1-04-init.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iikira/advanced-go-programming-book/1b5310f7547a5191d4687d94e0e6a9d32be61431/images/ch1-04-init.png -------------------------------------------------------------------------------- /images/ch1-08-ConEmu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iikira/advanced-go-programming-book/1b5310f7547a5191d4687d94e0e6a9d32be61431/images/ch1-08-ConEmu.png -------------------------------------------------------------------------------- /images/ch1-08-TextMate-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iikira/advanced-go-programming-book/1b5310f7547a5191d4687d94e0e6a9d32be61431/images/ch1-08-TextMate-1.png -------------------------------------------------------------------------------- /images/ch1-08-atom-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iikira/advanced-go-programming-book/1b5310f7547a5191d4687d94e0e6a9d32be61431/images/ch1-08-atom-01.png -------------------------------------------------------------------------------- /images/ch1-08-ios-textastic-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iikira/advanced-go-programming-book/1b5310f7547a5191d4687d94e0e6a9d32be61431/images/ch1-08-ios-textastic-02.png -------------------------------------------------------------------------------- /images/ch1-08-ios-textastic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iikira/advanced-go-programming-book/1b5310f7547a5191d4687d94e0e6a9d32be61431/images/ch1-08-ios-textastic.png -------------------------------------------------------------------------------- /images/ch1-08-ios-working-copy-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iikira/advanced-go-programming-book/1b5310f7547a5191d4687d94e0e6a9d32be61431/images/ch1-08-ios-working-copy-02.png -------------------------------------------------------------------------------- /images/ch1-08-ios-working-copy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iikira/advanced-go-programming-book/1b5310f7547a5191d4687d94e0e6a9d32be61431/images/ch1-08-ios-working-copy.png -------------------------------------------------------------------------------- /images/ch1-08-macos-textastic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iikira/advanced-go-programming-book/1b5310f7547a5191d4687d94e0e6a9d32be61431/images/ch1-08-macos-textastic.png -------------------------------------------------------------------------------- /images/ch1-08-npp-auto-completion.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iikira/advanced-go-programming-book/1b5310f7547a5191d4687d94e0e6a9d32be61431/images/ch1-08-npp-auto-completion.png -------------------------------------------------------------------------------- /images/ch1-08-npp-go-asm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iikira/advanced-go-programming-book/1b5310f7547a5191d4687d94e0e6a9d32be61431/images/ch1-08-npp-go-asm.png -------------------------------------------------------------------------------- /images/ch1-08-npp-go.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iikira/advanced-go-programming-book/1b5310f7547a5191d4687d94e0e6a9d32be61431/images/ch1-08-npp-go.png -------------------------------------------------------------------------------- /images/ch1-08-npp-proto.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iikira/advanced-go-programming-book/1b5310f7547a5191d4687d94e0e6a9d32be61431/images/ch1-08-npp-proto.png -------------------------------------------------------------------------------- /images/ch1-08-vscode-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iikira/advanced-go-programming-book/1b5310f7547a5191d4687d94e0e6a9d32be61431/images/ch1-08-vscode-01.png -------------------------------------------------------------------------------- /images/ch1-08-vscode-02.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iikira/advanced-go-programming-book/1b5310f7547a5191d4687d94e0e6a9d32be61431/images/ch1-08-vscode-02.jpg -------------------------------------------------------------------------------- /images/ch2-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|_cgo_export.c| 36 | :sum(2, 3); 37 | 38 | endfork 39 | 40 | |runtime.cgocall| 41 | :_cgo_runtime_cgocall(...); 42 | 43 | |main.go| 44 | stop 45 | 46 | @enduml 47 | -------------------------------------------------------------------------------- /images/ch2-call-c-sum-v1.uml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iikira/advanced-go-programming-book/1b5310f7547a5191d4687d94e0e6a9d32be61431/images/ch2-call-c-sum-v1.uml.png -------------------------------------------------------------------------------- /images/ch2-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-call-c-sum-v2.uml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iikira/advanced-go-programming-book/1b5310f7547a5191d4687d94e0e6a9d32be61431/images/ch2-call-c-sum-v2.uml.png -------------------------------------------------------------------------------- /images/ch2-cgo-generated-files.dot: -------------------------------------------------------------------------------- 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 | digraph G { 6 | subgraph cluster_cgo_package_main { 7 | label = "package main"; 8 | 9 | nocgo_x[label="nocgo_x.go", style=filled, color=gray]; 10 | hello_go[label="hello.go", style=filled, color=orangered4]; 11 | main_go[label="main.go", style=filled, color=darkgreen]; 12 | nocgo_1[label="nocgo_1.go", style=filled, color=gray]; 13 | } 14 | 15 | subgraph cluster_cgo_generated_files { 16 | label = "cgo: generated fileds"; 17 | 18 | main_cgo2_c[label="main.cgo2.c", style=filled, color=green]; 19 | main_cgo1_go[label="main.cgo1.go", style=filled, color=green]; 20 | 21 | hello_cgo2_c[label="hello.cgo2.c", style=filled, color=red]; 22 | hello_cgo1_go[label="hello.cgo1.go", style=filled, color=red]; 23 | 24 | _cgo_gotypes_go[label="_cgo_gotypes.go", shape=box, style=filled, color=dodgerblue]; 25 | _cgo_export_h[label="_cgo_export.h", shape=box, style=filled, color=dodgerblue]; 26 | _cgo_export_c[label="_cgo_export.c", shape=box, style=filled, color=dodgerblue]; 27 | 28 | main_go -> main_cgo1_go -> _cgo_gotypes_go; 29 | main_go -> main_cgo2_c -> _cgo_gotypes_go; 30 | 31 | hello_go -> hello_cgo1_go -> _cgo_gotypes_go; 32 | hello_go -> hello_cgo2_c -> _cgo_gotypes_go; 33 | 34 | _cgo_gotypes_go -> _cgo_export_h; 35 | _cgo_gotypes_go -> _cgo_export_c; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /images/ch2-cgo-generated-files.dot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iikira/advanced-go-programming-book/1b5310f7547a5191d4687d94e0e6a9d32be61431/images/ch2-cgo-generated-files.dot.png -------------------------------------------------------------------------------- /images/ch2-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-int32-to-char-ptr.uml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iikira/advanced-go-programming-book/1b5310f7547a5191d4687d94e0e6a9d32be61431/images/ch2-int32-to-char-ptr.uml.png -------------------------------------------------------------------------------- /images/ch2-qsort-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 qsort 8 | 9 | participant go 10 | participant c 11 | 12 | [--> go: qsort 13 | activate go 14 | 15 | go -> go 16 | activate go #DarkSalmon 17 | note left 18 | go_qsort_compare_info.elemsize = sv.Type().Elem().Size() 19 | go_qsort_compare_info.fn = fn 20 | end note 21 | 22 | deactivate go 23 | 24 | go -> c: C.qsort_proxy(cmp=go_qsort_compare) 25 | activate c 26 | note right 27 | void qsort_proxy( 28 | void* base, size_t num, size_t size, 29 | int (*compare)(const void* a, const void* b) 30 | ) { 31 | go_qsort_compare_save_base(base); 32 | qsort(base, num, size, compare); 33 | } 34 | end note 35 | 36 | ' begin 37 | c -> c: C.go_qsort_compare_save_base 38 | activate c #DarkSalmon 39 | note right: callback go func 40 | 41 | go <- c: go_qsort_compare_save_base 42 | activate go #DarkSalmon 43 | note left 44 | //export go_qsort_compare_save_base 45 | func go_qsort_compare_save_base(base unsafe.Pointer) { 46 | go_qsort_compare_info.base = uintptr(base) 47 | } 48 | var go_qsort_compare_info struct { 49 | base uintptr 50 | elemsize uintptr 51 | fn func(a, b int) int 52 | sync.RWMutex 53 | } 54 | end note 55 | 56 | go -> c: go_qsort_compare_save_base done 57 | deactivate go 58 | 59 | deactivate c 60 | ' end 61 | 62 | loop 63 | c -> c: C.go_qsort_compare 64 | activate c #DarkSalmon 65 | note right: callback go func 66 | 67 | c -> go: go_qsort_compare 68 | activate go #DarkSalmon 69 | note left 70 | //export go_qsort_compare_save_base 71 | func go_qsort_compare_save_base(base unsafe.Pointer) { 72 | go_qsort_compare_info.base = uintptr(base) 73 | } 74 | end note 75 | 76 | go -> c: go_qsort_compare done 77 | deactivate go 78 | 79 | deactivate c 80 | end 81 | 82 | go <- c: C.qsort_proxy done 83 | deactivate c 84 | 85 | [<-- go: done 86 | deactivate go 87 | 88 | @enduml 89 | -------------------------------------------------------------------------------- /images/ch2-qsort-v2.uml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iikira/advanced-go-programming-book/1b5310f7547a5191d4687d94e0e6a9d32be61431/images/ch2-qsort-v2.uml.png -------------------------------------------------------------------------------- /images/ch2-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-x-ptr-to-y-ptr.uml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iikira/advanced-go-programming-book/1b5310f7547a5191d4687d94e0e6a9d32be61431/images/ch2-x-ptr-to-y-ptr.uml.png -------------------------------------------------------------------------------- /images/ch2-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-x-slice-to-y-slice.uml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iikira/advanced-go-programming-book/1b5310f7547a5191d4687d94e0e6a9d32be61431/images/ch2-x-slice-to-y-slice.uml.png -------------------------------------------------------------------------------- /images/ch6-02-radix-get-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iikira/advanced-go-programming-book/1b5310f7547a5191d4687d94e0e6a9d32be61431/images/ch6-02-radix-get-1.png -------------------------------------------------------------------------------- /images/ch6-02-radix-get-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iikira/advanced-go-programming-book/1b5310f7547a5191d4687d94e0e6a9d32be61431/images/ch6-02-radix-get-2.png -------------------------------------------------------------------------------- /images/ch6-02-radix-get-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iikira/advanced-go-programming-book/1b5310f7547a5191d4687d94e0e6a9d32be61431/images/ch6-02-radix-get-3.png -------------------------------------------------------------------------------- /images/ch6-02-radix-get-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iikira/advanced-go-programming-book/1b5310f7547a5191d4687d94e0e6a9d32be61431/images/ch6-02-radix-get-4.png -------------------------------------------------------------------------------- /images/ch6-02-radix-put.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iikira/advanced-go-programming-book/1b5310f7547a5191d4687d94e0e6a9d32be61431/images/ch6-02-radix-put.png -------------------------------------------------------------------------------- /images/ch6-02-radix.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iikira/advanced-go-programming-book/1b5310f7547a5191d4687d94e0e6a9d32be61431/images/ch6-02-radix.png -------------------------------------------------------------------------------- /images/ch6-02-trie.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iikira/advanced-go-programming-book/1b5310f7547a5191d4687d94e0e6a9d32be61431/images/ch6-02-trie.png -------------------------------------------------------------------------------- /images/ch6-03-gin_contrib.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iikira/advanced-go-programming-book/1b5310f7547a5191d4687d94e0e6a9d32be61431/images/ch6-03-gin_contrib.png -------------------------------------------------------------------------------- /images/ch6-03-middleware_flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iikira/advanced-go-programming-book/1b5310f7547a5191d4687d94e0e6a9d32be61431/images/ch6-03-middleware_flow.png -------------------------------------------------------------------------------- /images/ch6-04-validate-struct-tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iikira/advanced-go-programming-book/1b5310f7547a5191d4687d94e0e6a9d32be61431/images/ch6-04-validate-struct-tree.png -------------------------------------------------------------------------------- /images/ch6-04-validate.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iikira/advanced-go-programming-book/1b5310f7547a5191d4687d94e0e6a9d32be61431/images/ch6-04-validate.jpg -------------------------------------------------------------------------------- /images/ch6-08-controller-logic-dao.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iikira/advanced-go-programming-book/1b5310f7547a5191d4687d94e0e6a9d32be61431/images/ch6-08-controller-logic-dao.png -------------------------------------------------------------------------------- /images/ch6-08-frontend-backend.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iikira/advanced-go-programming-book/1b5310f7547a5191d4687d94e0e6a9d32be61431/images/ch6-08-frontend-backend.png -------------------------------------------------------------------------------- /images/ch6-08-plugin-arch.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iikira/advanced-go-programming-book/1b5310f7547a5191d4687d94e0e6a9d32be61431/images/ch6-08-plugin-arch.jpg -------------------------------------------------------------------------------- /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 -------------------------------------------------------------------------------- /talks/README.md: -------------------------------------------------------------------------------- 1 | # 相关 报告 2 | 3 | - 深入CGO编程: https://github.com/chai2010/gopherchina2018-cgo-talk 4 | 5 | --------------------------------------------------------------------------------