一直有计划将 Delphi 中的譬如 TIniFile 等相关功能移植到 Golang,这些设施在 Delphi 中(相对而言)比较常用,使用起来也非常方便。

  虽然 Github 上早已有这些三方库,但我还是想仿照 Delphi 的做法来实现一套(其实只是模仿了 TMemIniFile 而非 Windows 下的 TIniFile 实现,暂时无意愿去实现 GetPrivateProfileXXX/WritePrivateProfileXXX 等 API),并额外提供直接干脆的调用接口等。

  代码已托管至 Github

// Copyright 2017 ecofast(无尽愿). All rights reserved.
// Use of this source code is governed by a BSD-style license. // Package iniutils was translated from TMemIniFile in Delphi(2007) RTL,
// which loads an entire INI file into memory
// and allows all operations to be performed on the memory image.
// The image can then be written out to the disk file.
package iniutils import (
"bufio"
"bytes"
"fmt"
"os"
"strconv"
"strings" "github.com/ecofast/sysutils"
) type IniFile struct {
fileName string
caseSensitive bool
sections map[string][]string
} func NewIniFile(filename string, casesensitive bool) *IniFile {
ini := &IniFile{
fileName: filename,
caseSensitive: casesensitive,
sections: make(map[string][]string),
}
ini.loadValues()
return ini
} func (ini *IniFile) FileName() string {
return ini.fileName
} func (ini *IniFile) CaseSensitive() bool {
return ini.caseSensitive
} func (ini *IniFile) String() string {
var buf bytes.Buffer
for sec, lst := range ini.sections {
buf.WriteString(fmt.Sprintf("[%s]\n", sec))
for _, s := range lst {
buf.WriteString(fmt.Sprintf("%s\n", s))
}
buf.WriteString("\n")
}
return buf.String()
} func (ini *IniFile) getRealValue(s string) string {
if !ini.caseSensitive {
return strings.ToLower(s)
}
return s
} func (ini *IniFile) loadValues() {
if !sysutils.FileExists(ini.fileName) {
return
} file, err := os.Open(ini.fileName)
if err != nil {
return
}
defer file.Close() section := ""
scanner := bufio.NewScanner(file)
for scanner.Scan() {
s := scanner.Text()
s = strings.TrimSpace(s)
s = ini.getRealValue(s)
if s != "" && s[0] != ';' {
if s[0] == '[' && s[len(s)-1] == ']' {
s = s[1 : len(s)-1]
section = s
} else {
if section != "" {
if pos := strings.Index(s, "="); pos > 0 {
if sl, ok := ini.sections[section]; ok {
ini.sections[section] = append(sl, s)
} else {
ini.sections[section] = []string{s}
}
} else {
// ingore invalid ident
//
}
}
}
}
}
} func (ini *IniFile) flush() {
file, err := os.Create(ini.fileName)
sysutils.CheckError(err)
defer file.Close() fw := bufio.NewWriter(file)
for sec, lst := range ini.sections {
_, err = fw.WriteString(fmt.Sprintf("[%s]\n", sec))
sysutils.CheckError(err) for _, s := range lst {
_, err = fw.WriteString(fmt.Sprintf("%s\n", s))
sysutils.CheckError(err)
} _, err = fw.WriteString("\n")
sysutils.CheckError(err)
}
fw.Flush()
} func (ini *IniFile) SectionExists(section string) bool {
sec := ini.getRealValue(section)
if _, ok := ini.sections[sec]; ok {
return true
}
return false
} func (ini *IniFile) ReadSections() []string {
var ss []string
for sec, _ := range ini.sections {
ss = append(ss, sec)
}
return ss
} func (ini *IniFile) EraseSection(section string) {
sec := ini.getRealValue(section)
delete(ini.sections, sec)
} func (ini *IniFile) ReadSectionIdents(section string) []string {
var ss []string
sec := ini.getRealValue(section)
if sl, ok := ini.sections[sec]; ok {
for _, s := range sl {
if pos := strings.Index(s, "="); pos > 0 {
ss = append(ss, s[0:pos])
}
}
}
return ss
} func (ini *IniFile) ReadSectionValues(section string) []string {
var ss []string
sec := ini.getRealValue(section)
if sl, ok := ini.sections[sec]; ok {
for _, s := range sl {
ss = append(ss, s)
}
}
return ss
} func (ini *IniFile) DeleteIdent(section, ident string) {
sec := ini.getRealValue(section)
id := ini.getRealValue(ident)
if sl, ok := ini.sections[sec]; ok {
for i := 0; i < len(sl); i++ {
s := sl[i]
if pos := strings.Index(s, "="); pos > 0 {
if s[0:pos] == id {
var ss []string
for j := 0; j < i; j++ {
ss = append(ss, sl[j])
}
for j := i + 1; j < len(sl); j++ {
ss = append(ss, sl[j])
}
ini.sections[sec] = ss
return
}
}
}
}
} func (ini *IniFile) IdentExists(section, ident string) bool {
sec := ini.getRealValue(section)
id := ini.getRealValue(ident)
if sl, ok := ini.sections[sec]; ok {
for _, s := range sl {
if pos := strings.Index(s, "="); pos > 0 {
if s[0:pos] == id {
return true
}
}
}
}
return false
} func (ini *IniFile) ReadString(section, ident, defaultValue string) string {
sec := ini.getRealValue(section)
id := ini.getRealValue(ident)
if sl, ok := ini.sections[sec]; ok {
for _, s := range sl {
if pos := strings.Index(s, "="); pos > 0 {
if s[0:pos] == id {
return s[pos+1:]
}
}
}
}
return defaultValue
} func (ini *IniFile) WriteString(section, ident, value string) {
sec := ini.getRealValue(section)
id := ini.getRealValue(ident)
if sl, ok := ini.sections[sec]; ok {
for i := 0; i < len(sl); i++ {
s := sl[i]
if pos := strings.Index(s, "="); pos > 0 {
if s[0:pos] == id {
var ss []string
for j := 0; j < i; j++ {
ss = append(ss, sl[j])
}
ss = append(ss, ident+"="+value)
for j := i + 1; j < len(sl); j++ {
ss = append(ss, sl[j])
}
ini.sections[sec] = ss
return
}
}
}
ini.sections[sec] = append(sl, ident+"="+value)
} else {
ini.sections[sec] = []string{ident + "=" + value}
}
} func (ini *IniFile) ReadInt(section, ident string, defaultValue int) int {
s := ini.ReadString(section, ident, "")
if ret, err := strconv.Atoi(s); err == nil {
return ret
} else {
return defaultValue
}
} func (ini *IniFile) WriteInt(section, ident string, value int) {
ini.WriteString(section, ident, strconv.Itoa(value))
} func (ini *IniFile) ReadBool(section, ident string, defaultValue bool) bool {
s := ini.ReadString(section, ident, sysutils.BoolToStr(defaultValue))
return sysutils.StrToBool(s)
} func (ini *IniFile) WriteBool(section, ident string, value bool) {
ini.WriteString(section, ident, sysutils.BoolToStr(value))
} func (ini *IniFile) ReadFloat(section, ident string, defaultValue float64) float64 {
s := ini.ReadString(section, ident, "")
if s != "" {
if ret, err := strconv.ParseFloat(s, 64); err == nil {
return ret
}
}
return defaultValue
} func (ini *IniFile) WriteFloat(section, ident string, value float64) {
ini.WriteString(section, ident, sysutils.FloatToStr(value))
} func (ini *IniFile) Close() {
ini.flush()
} func (ini *IniFile) Clear() {
ini.sections = make(map[string][]string)
} func IniReadString(fileName, section, ident, defaultValue string) string {
inifile := NewIniFile(fileName, false)
defer inifile.Close()
return inifile.ReadString(section, ident, defaultValue)
} func IniWriteString(fileName, section, ident, value string) {
inifile := NewIniFile(fileName, false)
defer inifile.Close()
inifile.WriteString(section, ident, value)
} func IniReadInt(fileName, section, ident string, defaultValue int) int {
inifile := NewIniFile(fileName, false)
defer inifile.Close()
return inifile.ReadInt(section, ident, defaultValue)
} func IniWriteInt(fileName, section, ident string, value int) {
inifile := NewIniFile(fileName, false)
defer inifile.Close()
inifile.WriteInt(section, ident, value)
} func IniSectionExists(fileName, section string) bool {
inifile := NewIniFile(fileName, false)
defer inifile.Close()
return inifile.SectionExists(section)
} func IniReadSectionIdents(fileName, section string) []string {
inifile := NewIniFile(fileName, false)
defer inifile.Close()
return inifile.ReadSectionIdents(section)
} func IniReadSections(fileName string) []string {
inifile := NewIniFile(fileName, false)
defer inifile.Close()
return inifile.ReadSections()
} func IniReadSectionValues(fileName, section string) []string {
inifile := NewIniFile(fileName, false)
defer inifile.Close()
return inifile.ReadSectionValues(section)
} func IniEraseSection(fileName, section string) {
inifile := NewIniFile(fileName, false)
defer inifile.Close()
inifile.EraseSection(section)
} func IniIdentExists(fileName, section, ident string) bool {
inifile := NewIniFile(fileName, false)
defer inifile.Close()
return inifile.IdentExists(section, ident)
} func IniDeleteIdent(fileName, section, ident string) {
inifile := NewIniFile(fileName, false)
defer inifile.Close()
inifile.DeleteIdent(section, ident)
}

  

  而 Delphi 的 RTL 里提供有非常多的方便、实用、简洁的函数如 IntToStr、FileExists、IncludeTrailingBackslash 等等等等,我也打算慢慢地移植一些到 Golang,算是造点基础的轮子吧。

// Copyright 2016~2017 ecofast(无尽愿). All rights reserved.
// Use of this source code is governed by a BSD-style license. // Package sysutils implements some useful system utility functions
// in the way of which Delphi(2007) RTL has done.
package sysutils import (
"fmt"
"os"
"path/filepath"
"strconv"
"strings"
) func CheckError(e error) {
if e != nil {
panic(e)
}
} func BoolToStr(b bool) string {
if b {
return "1"
}
return "0"
} func StrToBool(s string) bool {
if ret, err := strconv.ParseBool(s); err == nil {
return ret
}
return false
} func FloatToStr(f float64) string {
return fmt.Sprintf("%g", f)
} func GetApplicationPath() string {
path := filepath.Dir(os.Args[0])
return path + string(os.PathSeparator)
} func DirectoryExists(path string) bool {
fileInfo, err := os.Stat(path)
if err == nil && fileInfo.IsDir() {
return true
}
return false
} func FileExists(filename string) bool {
_, err := os.Stat(filename)
return err == nil || os.IsExist(err)
} func CreateFile(filename string) bool {
// os.MkdirAll(path.Dir(filename))
_, err := os.Create(filename)
if err == nil {
return true
}
return false
} func IncludeTrailingBackslash(path string) string {
if !strings.HasSuffix(path, string(os.PathSeparator)) {
return path + string(os.PathSeparator)
}
return path
}

  

  最后再来个 litelog,基本照搬的 Go Recipes 里的代码。

// Copyright 2016~2017 ecofast(无尽愿). All rights reserved.
// Use of this source code is governed by a BSD-style license. // Package litelog provides a logging infrastructure with an option
// to set the log level, log file and write log data into log file
package litelog import (
"io"
"io/ioutil"
"log"
"os"
) // holds the log level
type LogLvl int const (
// logs nothing
LvlNone LogLvl = iota
// logs everything
LvlTrace
// logs Info, Warnings and Errors
LvlInfo
// logs Warnings and Errors
LvlWarning
// just logs Errors
LvlError
) // package level variables which are pointers to log.Logger
var (
Trace *log.Logger
Info *log.Logger
Warning *log.Logger
Error *log.Logger
) // initializes log.Logger objects
func initLogger(trace, info, warn, err io.Writer, flags int) {
flag := log.Ldate | log.Ltime | log.Lshortfile
if flags != 0 {
flag = flags
}
Trace = log.New(trace, "[Trace] ", flag)
Info = log.New(info, "[Info] ", flag)
Warning = log.New(warn, "[Warning] ", flag)
Error = log.New(err, "[Error] ", flag)
} // Setup logging facilities
func Initialize(loglvl LogLvl, logflag int, logfile string) {
logFile, err := os.OpenFile(logfile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
if err != nil {
log.Fatalf("Error opening log file: %s", err.Error())
} switch loglvl {
case LvlTrace:
initLogger(logFile, logFile, logFile, logFile, logflag)
return
case LvlInfo:
initLogger(ioutil.Discard, logFile, logFile, logFile, logflag)
return
case LvlWarning:
initLogger(ioutil.Discard, ioutil.Discard, logFile, logFile, logflag)
return
case LvlError:
initLogger(ioutil.Discard, ioutil.Discard, ioutil.Discard, logFile, logflag)
return
default:
initLogger(ioutil.Discard, ioutil.Discard, ioutil.Discard, ioutil.Discard, logflag)
logFile.Close()
return
}
}

  这是示例代码和执行结果。

// litelogdemo project main.go
package main import (
"errors"
"flag"
"litelog" "github.com/ecofast/sysutils"
) func main() {
loglvl := flag.Int("loglvl", 0, "an integer value(0--4)")
flag.Parse()
litelog.Initialize(litelog.LogLvl(*loglvl), 0, sysutils.GetApplicationPath()+"logs.txt")
litelog.Trace.Println("=====Main started=====")
test()
err := errors.New("Sample error")
litelog.Error.Println(err.Error())
litelog.Trace.Println("=====Main completed=====")
} func test() {
litelog.Trace.Println("Test started")
for i := 0; i < 10; i++ {
litelog.Info.Println("Counter value is:", i)
}
litelog.Warning.Println("The counter variable is not being used")
litelog.Trace.Println("Test completed")
}

iniutils for Golang的更多相关文章

  1. Golang, 以17个简短代码片段,切底弄懂 channel 基础

    (原创出处为本博客:http://www.cnblogs.com/linguanh/) 前序: 因为打算自己搞个基于Golang的IM服务器,所以复习了下之前一直没怎么使用的协程.管道等高并发编程知识 ...

  2. 说说Golang的使用心得

    13年上半年接触了Golang,对Golang十分喜爱.现在是2015年,离春节还有几天,从开始学习到现在的一年半时间里,前前后后也用Golang写了些代码,其中包括业余时间的,也有产品项目中的.一直 ...

  3. TODO:Golang指针使用注意事项

    TODO:Golang指针使用注意事项 先来看简单的例子1: 输出: 1 1 例子2: 输出: 1 3 例子1是使用值传递,Add方法不会做任何改变:例子2是使用指针传递,会改变地址,从而改变地址. ...

  4. Golang 编写的图片压缩程序,质量、尺寸压缩,批量、单张压缩

    目录: 前序 效果图 简介 全部代码 前序: 接触 golang 不久,一直是边学边做,边总结,深深感到这门语言的魅力,等下要跟大家分享是最近项目 服务端 用到的图片压缩程序,我单独分离了出来,做成了 ...

  5. golang struct扩展函数参数命名警告

    今天在使用VSCode编写golang代码时,定义一个struct,扩展几个方法,如下: package storage import ( "fmt" "github.c ...

  6. golang语言构造函数

    1.构造函数定义 构造函数 ,是一种特殊的方法.主要用来在创建对象时初始化对象, 即为对象成员变量赋初始值,总与new运算符一起使用在创建对象的语句中.特别的一个类可以有多个构造函数 ,可根据其参数个 ...

  7. TODO:Golang语言TCP/UDP协议重用地址端口

    TODO:Golang语言TCP/UDP协议重用地址端口 这是一个简单的包来解决重用地址的问题. go net包(据我所知)不允许设置套接字选项. 这在尝试进行TCP NAT时尤其成问题,其需要在同一 ...

  8. golang的安装

    整理了一下,网上关于golang的安装有三种方式(注明一下,我的环境为CentOS-6.x, 64bit) 方式一:yum安装(最简单) rpm -Uvh http://dl.fedoraprojec ...

  9. golang枚举类型 - iota用法拾遗

    在c#.java等高级语言中,经常会用到枚举类型来表示状态等.在golang中并没有枚举类型,如何实现枚举呢?首先从枚举的概念入手. 1.枚举类型定义 从百度百科查询解释如下:http://baike ...

随机推荐

  1. l段子

    段子简介 L段子起源.L段子是开发者根据市场调查, 用户可在等候列车,飞机,或在公交车上无 聊之余使用本应用.打发无聊的时间,分为段 子,图片,活动和个人中心,用户可根据自己 喜好进入不同的区域.段子 ...

  2. Javascript基础知识总结一

    Javascript基础知识总结一 <!DOCTYPE html> <html> <head lang="en"> <meta chars ...

  3. Netty NIO 框架性能压测-短链接-对比Tomcat

    压测方案 准备多个文件大小分别为 1k 10k 100k 300k 使用ab分别按 [50,2000](按50逐渐叠加)压测服务,每次请求10W次 硬件信息:CPU:Intel(R) Xeon(R) ...

  4. CentOS下 pycharm开发环境搭建

    经过一系统列的折腾之后,我终于有高版本的python和我熟悉的输入法用了,下面来搭建pycharm下的python开发环境. 1.首先安装java jdk注意是JAVA 的JDK,不是JAVA VM什 ...

  5. 设置文本框左边显示的View

    效果:

  6. Html5三维全景

    先看DEMO:http://think.weiyingjia.cn/liuming/quanjing/out.html 准备: 1.一张或多张全景图片素材    2.pano2VR软件,链接:http ...

  7. winserver2008 DNS 很详细

    from http://www.it165.net/admin/html/201312/2182.html DNS(Domain Name System域名系统)区域化管理 分布式 层次性 域名空间结 ...

  8. windows10搭建django1.10.3+Apache2.4

    很多教程都是在linux上搭建,windows上似乎天生不太适合,但是我还是愿意试试这个坑. 首先 交代一下自己的环境 python3.5.2 64位 django 1.10.3 apache 2.4 ...

  9. CentOS7下Apache及Tomcat开启SSL

    安装: 复制代码 yum install -y openssl #使用openssl可手动创建证书 yum install -y httpd yum install -y mod_ssl 防火墙打开8 ...

  10. c语言的学习秘籍之链表

    刚翻出来的作品,有点低级,但希望能起到作用: #include<stdio.h>#include<stdlib.h>#include<time.h>#include ...