阅读go语言源代码1

前面大概说过bison与yacc的语法,那么其实go也是用bison来实现的,下面来说说怎么阅读go语言源代码。要看代码首先得找到代码的入口,怎么找呢?你可能首先想到grep main是的,一般来说这是一个没有争议的办法,但是对于go语言来说,这个办法对,也不对。怎么说呢?我们用gdb来进行debug就会看到所有的go语言程序的入口居然都在src/lib9/main.c里的main函数。


#include 
#define NOPLAN9DEFINES
#include 

extern void p9main(int, char**);

int
main(int argc, char **argv)
{
    p9main(argc, argv);
    exits("main");
    return 99; 
}

从go/include/libc.h中里我们可以看到这么一句


#ifndef NOPLAN9DEFINES
#define main    p9main
#endif

也就是说,在go语言源代码里main函数都重命名了,所有的函数入口都变成了src/lib9/mina.c,也实际的入口各自的代码里,因此说入口是各自的main这句话,对也不对。

那么先大概说一下go语言的代码结构


.
|-- bin//我自己定义的安装目录
|-- doc//相关文档,godoc就是利用这个目录
|   |-- codelab
|   |   `-- wiki
|   |-- codewalk
|   |-- devel
|   |-- gopher
|   |-- progs
|   `-- talks
|       `-- io2010
|-- include//一些全局的定义文件
|-- lib//一些lib9相关的全局库
|   |-- codereview
|   `-- godoc
|-- misc//一些工具
|   |-- arm
|   |-- bash
|   |-- bbedit
|   |-- cgo
|   |   |-- gmp
|   |   |-- life
|   |   `-- stdio
|   |-- dashboard
|   |   `-- godashboard
|   |-- emacs
|   |-- kate
|   |-- nacl
|   |-- vim
|   |   |-- ftdetect
|   |   `-- syntax
|   `-- xcode
|-- pkg//编译好的go库
|   `-- linux_amd64
|       |-- archive
|       |-- compress
|       |-- container
|       |-- crypto
|       |-- debug
|       |-- encoding
|       |-- exp
|       |-- go
|       |-- hash
|       |-- http
|       |-- image
|       |-- io
|       |-- os
|       |-- rpc
|       |-- runtime
|       `-- testing
|-- src
|   |-- cmd//go语言相关的程序
|   |   |-- 5a
|   |   |-- 5c
|   |   |-- 5g
|   |   |-- 5l
|   |   |-- 6a//amd64的汇编器
|   |   |-- 6c//amd64的c编译器
|   |   |-- 6g//amd64的编译器
|   |   |-- 6l//amd64的链接器
|   |   |-- 8a
|   |   |-- 8c
|   |   |-- 8g
|   |   |-- 8l
|   |   |-- cc
|   |   |-- cgo
|   |   |-- cov
|   |   |-- ebnflint
|   |   |-- gc
|   |   |-- godefs
|   |   |-- godoc
|   |   |-- gofmt
|   |   |-- goinstall
|   |   |-- gopack
|   |   |-- gotest
|   |   |-- goyacc
|   |   |-- hgpatch
|   |   |-- ld
|   |   |-- nm
|   |   `-- prof
|   |-- lib9//lib9相关的库
|   |   |-- fmt
|   |   `-- utf
|   |-- libbio//全局库
|   |-- libcgo//cgo的库
|   |-- libmach//库
|   `-- pkg//go库
|       |-- archive
|       |-- asn1
|       |-- big
|       |-- bufio
|       |-- bytes
|       |-- cmath
|       |-- compress
|       |-- container
|       |-- crypto
|       |-- debug
|       |-- ebnf
|       |-- encoding
|       |-- exec
|       |-- exp
|       |-- expvar
|       |-- flag
|       |-- fmt
|       |-- go
|       |-- gob
|       |-- hash
|       |-- html
|       |-- http
|       |-- image
|       |-- io
|       |-- json
|       |-- log
|       |-- math
|       |-- mime
|       |-- net
|       |-- netchan
|       |-- nntp
|       |-- once
|       |-- os
|       |-- patch
|       |-- path
|       |-- rand
|       |-- reflect
|       |-- regexp
|       |-- rpc
|       |-- runtime
|       |-- scanner
|       |-- sort
|       |-- strconv
|       |-- strings
|       |-- sync
|       |-- syscall
|       |-- syslog
|       |-- tabwriter
|       |-- template
|       |-- testing
|       |-- time
|       |-- unicode
|       |-- unsafe
|       |-- utf16
|       |-- utf8
|       |-- websocket
|       `-- xml
`-- test//测试
    |-- bench
    |-- bugs
    |-- chan
    |-- fixedbugs
    |   |-- bug083.dir
    |   |-- bug088.dir
    |   |-- bug106.dir
    |   |-- bug133.dir
    |   |-- bug160.dir
    |   |-- bug191.dir
    |   |-- bug222.dir
    |   |-- bug226.dir
    |   |-- bug248.dir
    |   `-- bug282.dir
    |-- garbage
    |-- interface
    |-- ken
    |-- nilptr
    `-- syntax

我们先来看一个go语言的hello world文件hello.go

package main

func main(){
    println("Hello World");
}

那么这个文件要被编译链接成一个可执行文件,那么要执行如下命令:

6g hello.o
6l hello.6 -o hello

很显然最关键的就是6g和6l两个程序,那么我们就从6g开始

首先gdb -tui打开tui界面的gdb程序

然后输入file 6g载入6g程序,就可以看到

/home/hoping/go/src/lib9/main.c,然后输入start后,step进入了/home/hoping/go/src/cmd/gc/lex.c的main函数

因此我们只需要看这个文件就大概可以看到程序的执行流程了。接下来暂时不需要gdb了,我们换vi和ctags。

在go目录执行ctags -R *来生成tag,然后用vi打开lex.c进入main函数,其实即使你看了这个函数也不会有太多收获。

正如我们前面说过的那样,6g是用bison的,那么显然我们需要找到bison文件和yylex函数即可。既然入口在gc文件夹,那么猜想y文件也在gc文件夹,于是进入ls *.y之后可以看到go.y。而go.y的输入全是由yylex函数来提供的。所以首先我们来看看yylex函数,在go文件夹下执行vim -t yylex,然后选择gc文件夹那个。

本文来自:ITEYE博客

感谢作者:javatgo

查看原文:阅读go语言源代码1

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。