有什么方法可以在print语句中以不带7,-48…etc的漂亮方式显示输出?

The code is given below

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

", "Size", annotations.VolSize)

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|
",
        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|
",
    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.

Thanks @icza, i found one more way, have a look on this :-)

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}}
Volume  : {{.Volume}}
Portal  : {{.Portal}}
Size    : 
{{.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