プログラミング言語 Go を読みながらメモ。
第一章 : https://qiita.com/Nabetani/items/077c6b4d3d1ce0a2c3fd
第二章 : https://qiita.com/Nabetani/items/d053304698dfa3601116
第三章 : https://qiita.com/Nabetani/items/2fd9c372fcd8383955a5
第四章 : https://qiita.com/Nabetani/items/59bfd00dc3323883a07f
第五章 : https://qiita.com/Nabetani/items/4b785f1c9b0b26d48475
第六章 : https://qiita.com/Nabetani/items/1c100394a65af6506187
第七章 : https://qiita.com/Nabetani/items/6553ad253af77661e915
第八章 : https://qiita.com/Nabetani/items/3b2e3964159cc292fe00
第九章 : https://qiita.com/Nabetani/items/c94e51aa29926a56159e
第十章と第十一章は省略。
第十二章 : https://qiita.com/Nabetani/items/2d63279465e7ab8c20a2
で。
十三章は、楽しい unsafe。
ポインタを使ってプライベートメンバを書き換える
まずはこんなイタズラから。
package main
import (
"fmt"
"os"
"reflect"
"unsafe"
)
func main() {
stdout := os.Stdout
vs := reflect.ValueOf(stdout).Elem()
file := vs.FieldByName("file")
pfd := file.Elem().FieldByName("pfd")
sysfd := pfd.FieldByName("Sysfd")
unsafePtrToFD := unsafe.Pointer(sysfd.Addr().Pointer())
intPtrToFD := (*int)(unsafePtrToFD)
fmt.Fprintln(stdout, "stdout?") // 標準出力に出る
*intPtrToFD = 2
fmt.Fprintln(stdout, "stderr?") // 標準エラーに出る!
}
本当にこれで「stderr?」は標準エラーに出た。
unsafe.Pointer
を使わないバージョンでは書き換え禁止だったけど、unsafe.Pointer
を使ったら書き換えられた。素晴らしい。
とにかく、邪悪な用途に使えることはわかった。面白い。
cgo で、C のコードを呼ぶ
本よりも
http://otiai10.hatenablog.com/entry/2014/06/24/082448
が参考になった。
package main
/*
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
char const * gcc_version(){
static char r[] = "123.123.123";
sprintf( r, "%d.%d.%d", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__ );
return r;
}
char const * clang_version(){
return __clang_version__;
}
int is_cpp(){
#if defined __cplusplus
return 1;
#else
return 0;
#endif
}
*/
import "C"
import "fmt"
func main() {
gv := C.gcc_version()
fmt.Printf("gcc_version : %v\n", C.GoString(gv))
//=> gcc_version : 4.2.1
cv := C.clang_version()
fmt.Printf("clang versoin : %v\n", C.GoString(cv))
//=> clang versoin : 9.1.0 (clang-902.0.39.1)
fmt.Printf("is_cpp() == %v\n", C.is_cpp())
//=> is_cpp() == 0
}
こんな感じ。
cgo で、C++ のコードを呼ぶ
C++ を go のソースに埋め込む方法はわからなかったので、別ファイルにした。
まずは C++
// clang++ -c hoge.cpp -o hoge.o
extern "C"
int is_cpp(){
#if defined __cplusplus
return 1;
#else
return 0;
#endif
}
を、コメントのとおりにビルドしておいて、
go にリンクする。
package main
/*
#cgo CFLAGS:
#cgo LDFLAGS: hoge.o
int is_cpp();
*/
import "C"
import "fmt"
func main() {
fmt.Printf("is_cpp() == %v\n", C.is_cpp())
}
と、ちゃんと C++ のコードが呼べる。
終りに
というわけで、読破した。
読破しただけなので、練習問題もやっていないし、まだ書けるという感じではない。
とはいえ、全体像はわかったような気になった。
本の評価はあんまり高くないんだけど、これより良い本があるような気もしないので仕方ないという感じ。
C++でいうところの「注解C++リファレンスマニュアル」、あるいは C でいうところの「S・P・ハービソン3世とG・L・スティール・ジュニアのCリファレンスマニュアル」のような本がほしい。
まあウェブを見ろということなんだと思う。