kitex出现:open conf/test/conf.yaml: no such file or directory

open conf/test/conf.yaml: no such file or directory

https://github.com/cloudwego/cwgo/issues/120
https://github.com/cloudwego/cwgo/issues/29

In the code generated using Kitex, unit testing returns an error as shown in the title. The reason for this error is that biz/servicethe unit testing method also requires complete framework testing instead of independent unit testing, just like spring boot needs to load the entire spring environment when performing unit testing.

See the obtained conf.yamlsource code:

func initConf() {
    
    
	prefix := "conf"
	confFileRelPath := filepath.Join(prefix, filepath.Join(GetEnv(), "conf.yaml"))
	content, err := ioutil.ReadFile(confFileRelPath)
	if err != nil {
    
    
		panic(err)
	}

	conf = new(Config)
	err = yaml.Unmarshal(content, conf)
	if err != nil {
    
    
		hlog.Error("parse yaml error - %v", err)
		panic(err)
	}
	if err := validator.Validate(conf); err != nil {
    
    
		hlog.Error("validate config error - %v", err)
		panic(err)
	}

	conf.Env = GetEnv()

	pretty.Printf("%+v\n", conf)
}

In the above code, GetEnv()the intermediate path of the yaml configuration file is obtained through the method. The method body is as follows:

func GetEnv() string {
    
    
	e := os.Getenv("GO_ENV")
	if len(e) == 0 {
    
    
		return "test"
	}
	return e
}

The above method is to obtain the directory of go env and has nothing to do with this project and needs to be modified. Obviously, you need to start the environment here, such as dev, online, testetc. This will be discussed in another article. Let’s start the project here.
GetEnv()Just write one first testand write the configuration in the conf file in that directory.

Then after configuring according to the above, it should become as follows:

prefix := "conf"
confFileRelPath := filepath.Join(prefix, filepath.Join("test", "conf.yaml"))
}

The path synthesized when calling this method is conf/test/conf.yamlso obviously it cannot be found.confThere are no structures outside the directory

At this time, you only need to conf.yamlset the search location to an absolute path, so that no matter which file is used, the configuration file will be queried from the absolute directory, and no error will be reported.

Go language provides os.Getwd()methods to obtain absolute paths.

It should be noted that this method is dynamic. It does not obtain the directory where the method is located but the directory where the file that calls the method is located. Therefore this method is not possible because the path should change with the location of the method call.

So use filepath.Abs()the method, which is to get the absolute path of a file. Here you can get the absolute path of conf and set conf.yamlthe path.

.refers to the current directory.

But this doesn't work, because the paths obtained in go are all dynamic, and the encapsulation of os.GetWd()or filepath.Abs()is formal, and will only be actually called when the value is actually assigned. as follows

Insert image description here
Called in the test environment to become the test environment address

Insert image description here

The main function call becomes the main function address

Insert image description here

So how to solve it?

The editor parses the path until the root path is obtained, and then configures the configuration file path through the root path. In this way, no matter which directory is called, the root path is first obtained and then the configuration file path is configured.

My thoughts are:

  1. Get the absolute path of the conf calleros.Getwd()
  2. Since go cannot obtain the absolute path of the entire project, it is necessary to parse the path to obtain the absolute path of the project.
  3. Use to filepath.Dir(currentDir)get the upper level directory
  4. Use the name of the last directory filepath.Base(currentDir)obtained 3and compare with the project root
  5. Equality indicates that the path is an absolute path.
  6. By 1,2,3,4,5calling it in any directory, no matter how the absolute address changes, you can get the project root directory.
  7. Root directory (the comparison of the project name can be obtained from the configuration file or the main function, don’t think of me hard-coding it in the code) [Optional]

Then the modified conf initConfcode is as follows:

func initConf() {
    
    
	// 主函数为最外层函数,路径为根地址,其它路径调用只可能在其子目录下
	// 获取调用者路径
	fakepath,err := os.Getwd()
	if err != nil{
    
    
		log.Fatal(errors.New("获取调用者路径失败"))
		panic(err)
	}
	// 循环比较路径的最后一位是否为根目录
	// 如果是根目录就停止,循环超20次自动停止(没有目录有这么多层)
	i := 0
	for {
    
    
		i++
		if filepath.Base(fakepath) == "food_platform" {
    
     // 这里的food_platform是最原始根目录路径名,也就是项目最外层文件名
			break
		}
		fakepath = filepath.Dir(fakepath)
		if i >= 20 {
    
    
			log.Fatal(errors.New("获取调用者路径失败"))
			panic(err)
		}
	}
	prefix := fakepath + "/cms_commodity/api/conf"
	// 获取配置文件路径
	confFileRelPath := filepath.Join(prefix, filepath.Join("test","conf.yaml"))

	content, err := ioutil.ReadFile(confFileRelPath)
	if err != nil {
    
    
		panic(err)
	}
	conf = new(Config)
	err = yaml.Unmarshal(content, conf)
	if err != nil {
    
    
		klog.Error("parse yaml error - %v", err)
		panic(err)
	}
	if err := validator.Validate(conf); err != nil {
    
    
		klog.Error("validate config error - %v", err)
		panic(err)
	}
	conf.Env = GetEnv()
	pretty.Printf("%+v\n", conf)
}

There are three places above that need to be modified based on actual conditions:

  1. /testThe static one written here can be obtained from the command line using os.Argsthe and flaglibrary.
  2. The condition for if judgment food_platformis the project name, the name of the top-level root project. This needs to be modified based on the actual situation. Of course, it can also be written in the configuration file or obtained from the command line.
  3. /cms_commodity/api/confThis is written in the code and is the path from the root directory to the configuration file. This requires that the structure of the project cannot be changed.

Guess you like

Origin blog.csdn.net/xwh3165037789/article/details/135130334