有没有办法在打印语句中以漂亮的方式显示输出,而不是显示7、-48等等?

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

Is there any way to show the output in pretty way without 7, -48 .... etc in print statements?

问题

以下是代码的翻译结果:

fmt.Printf("%7s: %-48s\n", "IQN", annotations.Iqn)
fmt.Printf("%7s: %-16s\n", "Volume", args[0])
fmt.Printf("%7s: %-15s\n", "Portal", annotations.TargetPortal)
fmt.Printf("%7s: %-6s\n\n", "Size", annotations.VolSize)

请注意,这是代码的翻译结果,不包括任何其他内容。

英文:

The code is given below

fmt.Printf("%7s: %-48s\n", "IQN", annotations.Iqn)
fmt.Printf("%7s: %-16s\n", "Volume", args[0])
fmt.Printf("%7s: %-15s\n", "Portal", annotations.TargetPortal)
fmt.Printf("%7s: %-6s\n\n", "Size", annotations.VolSize)

答案1

得分: 3

不,没有。

但是你可以编写一个实用函数来自动化所有这些操作,你只需要传递你想要漂亮打印的键值对。

让我们用以下类型来建模键值对:

type KeyValue struct {
    Key   string
    Value interface{}
}

注意,值可以是任何类型,不仅仅是字符串值。我们将在打印时使用默认格式。如果你想要除默认格式之外的其他格式,你可以将其转换为你喜欢的字符串格式,并将其设置为值。

漂亮打印的实用函数(下面解释):

var aligns = map[bool]string{true: "-"}

func printKeyValues(keyRight, valueRight bool, kvs ...KeyValue) {
    // 首先将值转换为字符串,并找到最大键和最大值的长度:
    values := make([]string, len(kvs))
    maxKey, maxValue := 0, 0
    for i, kv := range kvs {
        if length := utf8.RuneCountInString(kv.Key); length > maxKey {
            maxKey = length
        }
        values[i] = fmt.Sprint(kv.Value)
        if length := utf8.RuneCountInString(values[i]); length > maxValue {
            maxValue = length
        }
    }
    
    // 生成格式字符串:
    fs := fmt.Sprintf("%%%s%ds: %%%s%ds|\n",
        aligns[keyRight], maxKey+1, aligns[valueRight], maxValue+1)
    
    // 现在打印键值对:
    for i, kv := range kvs {
        fmt.Printf(fs, kv.Key, values[i])
    }
}

测试一下:

printKeyValues(false, true, []KeyValue{
    {"IQN", "asdfl;kj"},
    {"Volume", "asdf;lkjasdf"},
    {"Portal", "asdf"},
    {"Size", 12345678},
}...)

输出:

    IQN: asdfl;kj     |
 Volume: asdf;lkjasdf |
 Portal: asdf         |
   Size: 12345678     |

另一个测试:

printKeyValues(true, false, []KeyValue{
    {"IQN", "asdfl;kj"},
    {"Volume", "asdf;lkjasdf"},
    {"Portal", "asdf"},
    {"Size", 12345678},
}...)

输出:

IQN    :      asdfl;kj|
Volume :  asdf;lkjasdf|
Portal :          asdf|
Size   :      12345678|

你可以在Go Playground上尝试这些示例。

解释

printKeyValues()首先遍历键值对,并将值转换为字符串,使用fmt.Sprint()进行默认格式化。现在我们可以找到最大键长度和最大值长度。注意,字符串的长度不是len(s),因为它返回的是UTF-8编码的字节长度(这是Go在内存中存储字符串的方式)。为了获取字符数(或更准确地说是rune的数量),我们使用了utf8.RuneCountInString()

一旦我们有了这些信息,我们就可以生成格式字符串,其中使用了最大键长度和最大值长度。我们还将提供控制键和值是否左对齐或右对齐的可能性,在格式字符串中,这意味着右对齐时有一个-符号。为了在左对齐时得到一个空字符串"",在右对齐时得到一个"-",为了简洁起见,我使用了一个简单的映射:

var aligns = map[bool]string{true: "-"}

使用false索引这个映射会得到映射值类型的零值,即"",使用true索引会得到关联的值,即"-"。由于这个映射始终是相同的,我将它移到了函数外部(小优化)。

为了生成格式字符串,我们使用了fmt.Sprintf()

fs := fmt.Sprintf("%%%s%ds: %%%s%ds|\n",
    aligns[keyRight], maxKey+1, aligns[valueRight], maxValue+1)

注意,%符号需要加倍,因为在格式字符串中它是特殊字符。

最后一个任务是使用生成的格式字符串打印所有键值对。

英文:

No, there is not.

But you can write a utility function which automates all these, and all you need to do is pass the key-value pairs you want to pretty-print.

Let's model the key-values with this type:

type KeyValue struct {
	Key   string
	Value interface{}
}

Note the value may be of any type, not just a string value. We'll use the default formatting when printing it. If you want a format other than the default, you can always convert it to string to your liking, and set that as the value.

The pretty-print utility function (explanation follows below):

var aligns = map[bool]string{true: "-"}

func printKeyValues(keyRight, valueRight bool, kvs ...KeyValue) {
	// First convert values to string and find max key and max value lengths:
	values := make([]string, len(kvs))
	maxKey, maxValue := 0, 0
	for i, kv := range kvs {
		if length := utf8.RuneCountInString(kv.Key); length > maxKey {
			maxKey = length
		}
		values[i] = fmt.Sprint(kv.Value)
		if length := utf8.RuneCountInString(values[i]); length > maxValue {
			maxValue = length
		}
	}
	
	// Generate format string:
	fs := fmt.Sprintf("%%%s%ds: %%%s%ds|\n",
		aligns[keyRight], maxKey+1, aligns[valueRight], maxValue+1)
	
	// And now print the key-values:
	for i, kv := range kvs {
		fmt.Printf(fs, kv.Key, values[i])
	}
}

Testing it:

printKeyValues(false, true, []KeyValue{
	{"IQN", "asdfl;kj"},
	{"Volume", "asdf;lkjasdf"},
	{"Portal", "asdf"},
	{"Size", 12345678},
}...)

Output:

    IQN: asdfl;kj     |
 Volume: asdf;lkjasdf |
 Portal: asdf         |
   Size: 12345678     |

Another test:

printKeyValues(true, false, []KeyValue{
	{"IQN", "asdfl;kj"},
	{"Volume", "asdf;lkjasdf"},
	{"Portal", "asdf"},
	{"Size", 12345678},
}...)

Output:

IQN    :      asdfl;kj|
Volume :  asdf;lkjasdf|
Portal :          asdf|
Size   :      12345678|

Try the examples on the Go Playground.

Explanation

The printKeyValues() first ranges over the key-value pairs, and converts values to string values, using the default formatting by calling fmt.Sprint(). Now we can find the max key length and the max value length. Note that length of a string is not len(s), as that returns the byte-length in UTF-8 encoding (which is how Go stores strings in memory). Instead to get the number of characters (or more precisely the number of runes), we used utf8.RuneCountInString().

Once we have this, we can generate the format string where the max key length and max value length is used. We will also give the possibility to control whether we want to align keys and values to the left or right, in the format string this means a - sign in case of right alignment. To get an empty string "" in case of left and a "-" in case of right, for compact code I used a simple map:

var aligns = map[bool]string{true: "-"}

Indexing this map with false gives the zero value of the value type of the map which is "", and indexing it with true will give the associated value which is "-". And since this map is always the same, I moved it outside of the function (small optimization).

To generate the format string we used fmt.Sprintf():

fs := fmt.Sprintf("%%%s%ds: %%%s%ds|\n",
	aligns[keyRight], maxKey+1, aligns[valueRight], maxValue+1)

Note that % signs need to be doubled as that is special in format strings.

One final task remained: to use the generated format string to print all key-value pairs.

答案2

得分: -2

感谢@icza,我找到了另一种方法,请看一下:

package main

import (
	"text/template"
	"os"
)

func main() {
	type Annotations struct {
		IQN    string
		Volume string
		Portal string
		Size   string
	}
	annotation := Annotations{

		IQN:    "openebs.io",
		Volume: "vol",
		Portal: "10.29.1.1:3260",
		Size:   "1G",

	}
	tmpl, err := template.New("test").Parse("IQN     : {{.IQN}}\nVolume  : {{.Volume}}\nPortal  : {{.Portal}}\nSize    : {{.Size}}")
	if err != nil {
		panic(err)
	}
	err = tmpl.Execute(os.Stdout, annotation)
	if err != nil {
		panic(err)
	}
}

输出结果:

IQN     : openebs.io
Volume  : vol
Portal  : 10.29.1.1:3260
Size    : 1G

这是链接 The Go Playground

英文:

Thanks @icza, i found one more way, have a look on this 有没有办法在打印语句中以漂亮的方式显示输出,而不是显示7、-48等等?

package main

import (
  "text/template"
  "os"
)

func main() {
   type Annotations struct {
	 IQN	string
	 Volume string
	 Portal string
	 Size   string
   }
   annotation := Annotations{

	 IQN: "openebs.io",
	 Volume: "vol",
	 Portal: "10.29.1.1:3260",
	 Size: "1G",
	
   }
   tmpl, err := template.New("test").Parse("IQN     : 
{{.IQN}}\nVolume  : {{.Volume}}\nPortal  : {{.Portal}}\nSize    : 
{{.Size}}")
   if err != nil {
    	panic(err)
	}
  err = tmpl.Execute(os.Stdout, annotation)
  if err != nil {
    	panic(err)
  }
}

Output :

IQN     : openebs.io
Volume  : vol
Portal  : 10.29.1.1:3260
Size    : 1G

Here is the link The Go Playground

huangapple
  • 本文由 发表于 2017年7月26日 14:47:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/45319427.html
匿名

发表评论

匿名网友

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

确定