这个函数的“惯用”版本是什么?

huangapple go评论88阅读模式
英文:

What is the "idiomatic" version of this function?

问题

尝试理解Go语言的思维方式。我编写了以下函数,用于查找文件夹中具有日期的*.txt文件,获取最新的日期并返回该日期。

func getLatestDate(path string) (time.Time, error) {
    if fns, e := filepath.Glob(filepath.Join(path, "*.txt")); e == nil {
        re, _ := regexp.Compile(`_([0-9]{8}).txt$`)
        max := ""
        for _, fn := range fns {
            if ms := re.FindStringSubmatch(fn); ms != nil {
                if ms[1] > max {
                    max = ms[1]
                }
            }
        }
        date, _ := time.Parse("20060102", max)
        return date, nil
    } else {
        return time.Time{}, e
    }
}

如果有更符合Go语言习惯的版本,它会是什么样子呢?

英文:

Trying to understand the mentality of Go. I wrote the following function which looks for *.txt files of a folder that have a date in the filename, get the latest date and return that date.

func getLatestDate(path string) (time.Time, error) {
	if fns, e := filepath.Glob(filepath.Join(path, "*.txt")); e == nil {
		re, _ := regexp.Compile(`_([0-9]{8}).txt$`)
		max := ""
		for _, fn := range fns {
			if ms := re.FindStringSubmatch(fn); ms != nil {
				if ms[1] > max {
					max = ms[1]
				}
			}
		}
		date, _ := time.Parse("20060102", max)
		return date, nil
	} else {
		return time.Time{}, e
	}
}

What would be the more idiomatic version of this function, if there is one?

答案1

得分: 11

这是我的建议:

  1. 使用MustCompile编译静态正则表达式。如果无法编译,它会引发错误并保存错误检查。
  2. 将编译正则表达式的过程提升到函数外部 - 只需要编译一次。请注意,我将其以小写字母开头,这样在包外部将不可见。
  3. 在检查错误时使用早期返回 - 这样可以减少缩进,并符合Go的惯用法。
  4. 对于这些早期返回,使用命名返回参数 - 这样可以避免为类型定义nil值和进行类型输入(尽管不是每个人都喜欢这样做)。
  5. 直接返回time.Parse,它会检查错误(之前你没有这样做)。

代码示例:

var dateRe = regexp.MustCompile(`_([0-9]{8}).txt$`)

func getLatestDate(path string) (date time.Time, err error) {
	fns, err := filepath.Glob(filepath.Join(path, "*.txt"))
	if err != nil {
		return
	}
	max := ""
	for _, fn := range fns {
		if ms := dateRe.FindStringSubmatch(fn); ms != nil {
			if ms[1] > max {
				max = ms[1]
			}
		}
	}
	return time.Parse("20060102", max)
}
英文:

Here is my take

  1. Use MustCompile to compile a static regexp. This will panic if it doesn't compile and saves an error check
  2. Hoist compiling the regexp out of the function - you only need it compiled once. Note that I've called it with a lowercase initial letter so it won't be visible outside the package.
  3. Use an early return when checking errors - this saves indentation and is idiomatic go
  4. Use named return parameters for those early returns - saves defining nil values for types and typing in general (not to everyone's taste though)
  5. return time.Parse directly which checks the errors (you weren't before)

The code

var dateRe = regexp.MustCompile(`_([0-9]{8}).txt$`)

func getLatestDate(path string) (date time.Time, err error) {
	fns, err := filepath.Glob(filepath.Join(path, "*.txt"))
	if err != nil {
		return
	}
	max := ""
	for _, fn := range fns {
		if ms := dateRe.FindStringSubmatch(fn); ms != nil {
			if ms[1] > max {
				max = ms[1]
			}
		}
	}
	return time.Parse("20060102", max)
}

答案2

得分: 0

这是我会如何编写它。不要忽略错误,使用守卫子句进行错误处理,并且不要在循环内重新编译正则表达式。

var datePat = regexp.MustCompile(`_([0-9]{8}).txt$`)

func getLatestDate(path string) (time.Time, error) {
    fns, err := filepath.Glob(filepath.Join(path, "*.txt"))
    if err != nil {
        return time.Time{}, err
    }
    max := time.Time{}
    for _, fn := range fns {
        if ms := re.FindStringSubmatch(fn); ms != nil {
            if t, err := time.Parse("20060102", ms[1]); err == nil && t.After(max) {
                max = t
            }
        }
    }
    return max, nil
}
英文:

Here's how I would have written it. Don't ignore errors, use guard clauses for error handling, and don't recompile regexps inside a loop.

var datePat = regexp.MustCompile(`_([0-9]{8}).txt$`)

func getLatestDate(path string) (time.Time, error) {
    fns, err := filepath.Glob(filepath.Join(path, "*.txt"))
    if err != nil {
        return time.Time{}, err
    }
    max := time.Time{}
    for _, fn := range fns {
        if ms := re.FindStringSubmatch(fn); ms != nil {
            if t, err := time.Parse("20060102", ms[1]); err == nil && t.After(max) {
                max = t
            }
        }
    }
    return max, nil
}

huangapple
  • 本文由 发表于 2013年11月17日 16:04:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/20028579.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定