-
今日单词
incarnation
/ˌɪnkɑːˈneɪʃn; ˌɪnkɑr`neʃən/
-
n [C] person that prominently displays a particular quality (突出表现某种品质的)典型人物,化身
She is the very incarnation of goodness.
-
n [C,U] (instance of) being alive in human form 化身
the nine incarnations of Vishnu
He believed he had been a prince in a previous incarnation.
-
-
Makefile 中四种变量赋值的不同
http://stackoverflow.com/questions/448910/makefile-variable-assignment
Lazy Set
VARIABLE = value
当变量被用到的时候, 会递归的展开
Imeediate Set
VARIABLE := value
变量在申明的时候马上执行
Set If Absent
VARIABLE ?= value
变量不存在的时候才赋值(也是lazy set)
Append
VARIABLE += value
把value添加到已存在的变量后(如果变量不存在, 把value赋值给这个变量)
-
今日单词
obscurity
This is an obscurity that catches the unwary.
/əbˈskjʊərətɪ; əb`skjᴜrətɪ/
-
n U
state of being obscure 不明;费解;隐晦;无闻
content to live in obscurity
-
n C
thing that is obscure or indistinct 晦涩或不明的事物
a philosophical essay full of obscurity
-
-
规则长什么样子
https://www.gnu.org/software/make/manual/html_node/Rule-Introduction.html
一个简单的makefile包含下面这样的一个或者多个规则
target … : prerequisites … recipe … …
A target is usually the name of a file that is generated by a program; examples of targets are executable or object files. A target can also be the name of an action to carry out, such as ‘clean’ (see Phony Targets).
target(目标)通常是一个文件的名字并且是由接下来的recipe生成. 也可以是一个动作, 比如说clean. (参考Phony Targets)
A prerequisite is a file that is used as input to create the target. A target often depends on several files.
一个prerequisite(先决条件)就是目标的一个输入. 经常来说, 一个目标依赖多个先决条件. (译者注: 但实际上, 先决条件不仅仅可以是一个文件, 也可以是另外的target, 是链式依赖的)
A recipe is an action that make carries out. A recipe may have more than one command, either on the same line or each on its own line. Please note: you need to put a tab character at the beginning of every recipe line! This is an obscurity that catches the unwary. If you prefer to prefix your recipes with a character other than tab, you can set the .RECIPEPREFIX variable to an alternate character (see Special Variables).
Usually a recipe is in a rule with prerequisites and serves to create a target file if any of the prerequisites change. However, the rule that specifies a recipe for the target need not have prerequisites. For example, the rule containing the delete command associated with the target ‘clean’ does not have prerequisites.
A rule, then, explains how and when to remake certain files which are the targets of the particular rule. make carries out the recipe on the prerequisites to create or update the target. A rule can also explain how and when to carry out an action. See Writing Rules.
A makefile may contain other text besides rules, but a simple makefile need only contain rules. Rules may look somewhat more complicated than shown in this template, but all fit the pattern more or less.
-
Makefile 简介
https://www.gnu.org/software/make/manual/html_node/Introduction.html
make需要一个Makefile, Makefile告诉make如何编译和链接.
这章会讨论一个简单的makefile, 描述了如何编译和链接一个文本编辑器程序,此程序由8个C文件和3个头文件组成.
make重新编译程序的时候, 会保证每一个有新变化的C文件被重新编译, 如果头文件有变动, 每个包含这个头文件的C文件也需要重新编译. 每个编译会生成一个对象文件, 然后再把所有对象文件链接生成新的可执行程序.
-
今日单词
recipe
|ˈresəpi| n
-
~ (for sth) set of instructions for preparing food dish, including ingredients required. 烹饪法;食谱 [做定语]
recipe books, cards
-
~ for sth (fig 比喻) method of achieving sth 方法;秘诀;诀窍
what is your recipe for success?
His plans are a recipe for disaster.
-
-
how to write go code
看了https://golang.org/doc/code.html, 觉得主要是讲了关于golang的Lib组织形式, 简单记录一下.
简介
本文描述了获取,构造和安装Go包以及Go工具的标准方法. go tool(就是go这个命令, 下面包含build run等命令)需要把你的代码按一定的格式组织起来.
代码组织
概述
- 一般来说, 所有的Go代码都放在一个单独的workspace
- 一个workspace包含多个版本控制仓库
- 每个仓库里面包括一个或者多个packages
- 一个package包含一个或者多个Go源代码, 这些源代码需要在一个单独的目录下面
- package的路径决定了它的import path
Workspaces
一个workspace是这样一个目录结构, 包括下面三个子目录:
- src 包含Go的源码
- pkg 包含packagecfqj
- bin 包含可执行命令
go tool会build源码, 然后把结构安装到pkg和bin目录下.
GOPATH 环境变量
GOPATH环境变量定义的你的workspace位置. 它是你需要的惟一一个环境变量. 它一定不能Go的安装路径使用同一个目录.
$ mkdir $HOME/work $ export GOPATH=$HOME/work
为了方便, 可以把bin子目录放在PATH变量下
$ export PATH=$PATH:$GOPATH/bin
import path
import path是能惟一确认package路径的字符串.
标准库的路径都是一个短路径, 像fmt, net/http. 你自己的代码, 需要选一个基础路径, 尽量不要和以后的标准库或者其他的第三方库有冲突.
比如说可以用 github.com/user做为基础路径, 在workspace下面新建一个目录存放你的源码.
你的第一个程序
在workspace目录下, 新建一个package目录做为package path.
$ mkdir $GOPATH/src/github.com/user/hello
下一步, 在这个目录下创建一个hello.go:
package main import "fmt" func main() { fmt.Printf("Hello, world.\n") }
下面就可以build和install你的程序.
$ go install github.com/user/hello
注意, 你可以在任意路径下运行这个命令, go会自己找到的. 如果你已经在包目录下面了, 直接跑 go install 也可以.
$ cd $GOPATH/src/github.com/user/hello $ go install
会在GOPATH/bin下面生成一个hello可执行文件.
你的第一个库
让我们来写一个库, 并在hello中调用它
同样的, 先选一个package路径, 在这里我们用github.com/user/stringutil.
$ mkdir $GOPATH/src/github.com/user/stringutil
在这个路径下创建go文件, reverse.go
// Package stringutil contains utility functions for working with strings. package stringutil // Reverse returns its argument string reversed rune-wise left to right. func Reverse(s string) string { r := []rune(s) for i, j := 0, len(r)-1; i < len(r)/2; i, j = i+1, j-1 { r[i], r[j] = r[j], r[i] } return string(r) }
现在可以build了(好像没什么用, 就是测试一下是不是能编译)
$ go build github.com/user/stringutil
不会生成任何文件. 如果来
go install
, 可以在pkg目录下生成package对象.我们在hello中引用它, 修改$GOPATH/src/github.com/user/hello/hello.go
package main import ( "fmt" "github.com/user/stringutil" ) func main() { fmt.Printf(stringutil.Reverse("!oG ,olleH")) }
安装hello, 同时它的依赖(stringutil)也会被安装.
$ go install github.com/user/hello
Package names
go源码的第一行必须是
package name
在这里, name就是这个包被引用用的名字,一个包里面的所有文件都必须用同一个名字.
包名需要是引用路径的最后一个元素, 如果包被引用为srypto/rto13, 包名则应该是rto13.
可执行文件的名字一定要是main.
一个二进制文件中引用的包, 并不要求它们的名字不一样, 但是完整路径肯定不能相同.
-
今日单词
idiomatic
See Effective Go for tips on writing clear, idiomatic Go code.
ˌɪdɪəˈmætɪk
adj
(a) in accordance with the particular nature or structure of a language, dialect, etc 符合某一语言或者方言的习惯或者特点的She speaks fluent and idiomatic French. 她说得一口又流利又地道的法语.
(b) containing an idiom or idoms 含有习语的
an idiomatic expression, language 固定词组,成语多的语言.
-
今日单词
sparingly
Use parent-child relationships sparingly, and only when there are many more children than parents.
ˈspeərɪŋli
adv 节俭地 ‹spend›; 量少地 ‹eat›; 谨慎地 ‹praise›
to use something sparingly
she gives her advice sparingly
-
O_CLOEXEC 2
接上午的问题 O_CLOEXEC, execve呢, 就是exec系列函数中的一个,具体可以参见Unix环境高级编程第二版8.10节.
当进程调用一种exec函数时, 该进程执行的程序完全替换成新进程,而新程序则从其main函数开始执行. 因为exec并不创建新进程,所以前后的进程ID并未改变. exec只是用一个全新的程序替换了当前进程的正文,数据,堆和栈段.
现在来测试一下O_CLOEXEC这个参数的作用.
貌似, 一般来说, exec会在folk之后调用. 为了让例子看起来更简单, 我就在当前程序中调用exec. 测试的大概流程是这样.
先不带O_CLOEXEC这个参数, 打开一个文件. 然后再exec一个sleep程序, sleep 10秒.
程序运行时, 新开一个shell拿lsof观察被打开的文件, 是否被占用.如果不带O_CLOEXEC参数打开文件, 在exec之后, 这个文件使用被占用.
如果带O_CLOEXEC参数打开文件, exec之后, 文件就不再被占用了.
cloexec.c
#include <stdio.h> #include <unistd.h> #include <fcntl.h> int main(int argc, const char *argv[]) { int fd = open("cloexec.c",O_RDWR); printf("%d\n",fcntl(fd, F_GETFD, FD_CLOEXEC)); sleep(5); execl("/tmp/cloexec/sleep",(char *)0); return 0; }
sleep.c
#include <unistd.h> #include <stdio.h> int main(int argc, const char *argv[]) { sleep(5); printf("sleep done\n"); return 1; }