我们知道,我们编译.java并运行.class文件时,需要一些java命令,如最简单的helloworld程序。
这里的程序最好不要加包名,因为加了包名的话编译和运行需要有所改动。
看这里的命令。javac为编译命令,我们知道java的特点是一次编译,到处运行。这里的编译指的就是javac,对于java程序即.java文件,先要用javac编译成字节码。然后将字节码(.class文件)放到java虚拟机中运行,即上图中的java HelloWorld,java虚拟机把字节码翻译成对应机器上的机器指令,再由机器来执行具体的机器指令。也就是说java程序员是直接与java虚拟机交互,简介与机器交互。所以虚拟机完成的是java命令,也就是我们要完成的是java这个指令的功能。
那么我们把第一个目标定为,实现简单的命令行。即我们通过命令行可以输入一些内容,虚拟机读取之后可以给一定的反馈。
GO语言中有两个和命令行相关的包,分别是os和flag(java中以类库即jar文件导入,go中直接以包的形式导入)。
首先在GOPATH目录下的src里面新建一个jvmgo文件夹作为我们的工作空间目录,jvmgo里面再新建一个ch01为我们的第一个目标源码文件夹,添加cmd.go文件。
在cmd.go里面输入如下代码(由于博客园的添加代码方式不支持go语言着色,所以采用C语言着色,高亮可能不太正确)
package main import "flag" import "fmt" import "os" //定义Cmd结构体 type Cmd struct{ helpFlag bool versionFlag bool cpOption string class string args []string } //解析命令行参数 func parseCmd() *Cmd { cmd:=&Cmd{} //将printUsage函数传给flag.Usage flag.Usage=printUsage //设置各种解析的选项 flag.BoolVar(&cmd.helpFlag, "help", false, "print help message") flag.BoolVar(&cmd.helpFlag, "?", false, "print help message") flag.BoolVar(&cmd.versionFlag, "version", false, "print version and exit") flag.StringVar(&cmd.cpOption, "classpath", "", "classpath") flag.StringVar(&cmd.cpOption, "cp", "", "classpath") //所有选项设置完成后调用flag.Parse解析所有选项,如果Parse失败,则调用flag.Usage打印帮助信息 flag.Parse() //调用flag.Args函数捕获未被解析的参数,第一个参数为主类名,后面的为传递给主类的参数 args:=flag.Args() if len(args)>0{ cmd.class=args[0] cmd.args=args[1:] } return cmd } func printUsage() { fmt.Printf("Usage:%s[-options] class [args...]\n",os.Args[0]) }