인쇄하지 않고 Go 문자열을 포맷 하시겠습니까?


381

Go에서 문자열을 인쇄하지 않고 문자열을 포맷하는 간단한 방법이 있습니까?

내가 할 수있는:

bar := "bar"
fmt.Printf("foo: %s", bar)

그러나 형식화 된 문자열을 인쇄하지 않고 반환하여 더 조작 할 수 있기를 원합니다.

나는 또한 다음과 같은 것을 할 수있다 :

s := "foo: " + bar

그러나 형식 문자열이 복잡하면 읽기가 어렵고 하나 또는 많은 부분이 문자열이 아니고 먼저 변환 해야하는 경우 번거 롭습니다.

i := 25
s := "foo: " + strconv.Itoa(i)

더 간단한 방법이 있습니까?

답변:


465

Sprintf 는 당신이 찾고있는 것입니다.

fmt.Sprintf("foo: %s", bar)

"A Tour of Go"의 일부로 오류 예제 에서 사용중인 것을 볼 수도 있습니다 .

return fmt.Sprintf("at %v, %s", e.When, e.What)

6
% 이후의 문자가 중요합니까? % y 및 % q 일 수 있습니까? 또는 % y 및 % y
Filip Bartuzi

17
문자는 문제입니다. 동사라고합니다. 기본적으로 Sprintf가 변수의 유형을 알려주므로 65를 받고 동사가 % d이면 숫자 65를 인쇄하지만 동사가 % c이면 문자를 인쇄합니다 'ㅏ'. 참조 : golang.org/pkg/fmt/#hdr-Printing
redsalt

2
왜 Sprintf라고 불리는가? 문자열의 경우 S, 형식의 경우 f? 함수가 화면에 출력되지 않으면 인쇄가 함수 이름의 일부인 것이 이상합니다. 이것은 나를 잠시 당황하게했다 ...
jcollum

194

1. 간단한 문자열

"단순한"문자열 (일반적으로 줄에 맞는 것)의 경우 가장 간단한 솔루션은 fmt.Sprintf()친구 ( fmt.Sprint(), fmt.Sprintln())를 사용하는 것입니다. 이것들은 시작 S문자가 없는 함수와 유사 하지만 이러한 Sxxx()변형은 결과를 string표준 출력으로 인쇄 하는 대신 결과를 반환합니다 .

예를 들면 다음과 같습니다.

s := fmt.Sprintf("Hi, my name is %s and I'm %d years old.", "Bob", 23)

변수 s는 다음 값으로 초기화됩니다.

Hi, my name is Bob and I'm 23 years old.

팁 : 다른 유형의 값을 연결하려는 경우 정확히 이와 Sprintf()같이 자동으로 형식 문자열이 필요 하지 않을 수 있습니다 Sprint(). 이 예제를보십시오 :

i := 23
s := fmt.Sprint("[age:", i, "]") // s will be "[age:23]"

strings 만 연결 strings.Join()하는 경우 사용자 지정 구분 기호를 지정할 수 string있는 위치 (연결할 문자열 사이에 위치)를 사용할 수도 있습니다.

Go Playground 에서 사용해보십시오 .

2. 복잡한 문자열 (문서)

만들려는 문자열이 더 복잡하면 (예 : 여러 줄 전자 메일 메시지) fmt.Sprintf()읽기 어렵고 효율성이 떨어집니다 (특히 여러 번 수행해야하는 경우).

이를 위해 표준 라이브러리는 패키지를 제공 text/template하고 html/template. 이 패키지는 텍스트 출력을 생성하기위한 데이터 기반 템플릿을 구현합니다. html/template코드 삽입에 대해 안전한 HTML 출력을 생성하기위한 것입니다. 패키지 text/template와 동일한 인터페이스를 제공하며 text/template출력이 HTML 일 때마다 대신 사용해야합니다 .

template패키지를 사용하려면 기본적으로 string정적 텍스트를 포함 할 수 있는 값 (파일 이름 만 제공하는 경우 파일에서 시작될 수 있음) 형식으로 정적 템플릿을 제공해야합니다. 엔진은 템플릿을 처리하고 출력을 생성합니다.

정적 템플릿에 포함 / 대체되고 출력 생성 프로세스를 제어 할 수있는 매개 변수를 제공 할 수 있습니다. 그러한 파라미터의 전형적인 형태는 중첩 될 수있는 structs 및 map값이다.

예:

예를 들어 다음과 같은 이메일 메시지를 생성한다고 가정 해 보겠습니다.

Hi [name]!

Your account is ready, your user name is: [user-name]

You have the following roles assigned:
[role#1], [role#2], ... [role#n]

이와 같은 이메일 메시지 본문을 생성하려면 다음 정적 템플릿을 사용할 수 있습니다.

const emailTmpl = `Hi {{.Name}}!

Your account is ready, your user name is: {{.UserName}}

You have the following roles assigned:
{{range $i, $r := .Roles}}{{if $i}}, {{end}}{{.}}{{end}}
`

실행을 위해 다음과 같은 데이터를 제공하십시오.

data := map[string]interface{}{
    "Name":     "Bob",
    "UserName": "bob92",
    "Roles":    []string{"dbteam", "uiteam", "tester"},
}

일반적으로 템플릿의 출력은에 작성 io.Writer되므로 결과를로 string작성하려면 bytes.Buffer(구현하는 io.Writer)에 작성하고 씁니다 . 템플릿을 실행하고 결과를 string다음 과 같이 얻습니다 .

t := template.Must(template.New("email").Parse(emailTmpl))
buf := &bytes.Buffer{}
if err := t.Execute(buf, data); err != nil {
    panic(err)
}
s := buf.String()

결과는 다음과 같습니다.

Hi Bob!

Your account is ready, your user name is: bob92

You have the following roles assigned:
dbteam, uiteam, tester

Go Playground 에서 사용해보십시오 .

또한 이동 1.10 이후 새로운,보다 빠르고 전문 대안에 사용할 수 있음을 참고 bytes.Buffer인 : strings.Builder. 사용법은 매우 유사합니다.

builder := &strings.Builder{}
if err := t.Execute(builder, data); err != nil {
    panic(err)
}
s := builder.String()

Go Playground 에서 이것을 사용해보십시오 .

참고 : os.Stdout대상으로 제공하면 템플릿 실행 결과를 표시 할 수도 있습니다 (또한 구현 함 io.Writer).

t := template.Must(template.New("email").Parse(emailTmpl))
if err := t.Execute(os.Stdout, data); err != nil {
    panic(err)
}

결과를에 직접 씁니다 os.Stdout. Go Playground 에서 이것을 시도하십시오 .


2

귀하의 경우 형식 문자열에 Sprintf ()를 사용해야합니다.

func Sprintf(format string, a ...interface{}) string

Sprintf는 형식 지정자에 따라 형식을 지정하고 결과 문자열을 반환합니다.

s := fmt.Sprintf("Good Morning, This is %s and I'm living here from last %d years ", "John", 20)

출력은 다음과 같습니다.

좋은 아침입니다. 저는 존이며 지난 20 년 동안 이곳에 살고 있습니다.


0

fmt.SprintF 함수는 문자열을 반환하며 fmt.PrintF 와 동일한 방식으로 문자열을 형식화 할 수 있습니다.


0

를 통해 우리는 할 수있는 사용자 정의 새로운 문자열 유형 define new TypeFormat지원을 제공합니다.

package main

import (
    "fmt"
    "text/template"
    "strings"
)

type String string
func (s String) Format(data map[string]interface{}) (out string, err error) {
    t := template.Must(template.New("").Parse(string(s)))
    builder := &strings.Builder{}
    if err = t.Execute(builder, data); err != nil {
        return
    }
    out = builder.String()
    return
}


func main() {
    const tmpl = `Hi {{.Name}}!  {{range $i, $r := .Roles}}{{if $i}}, {{end}}{{.}}{{end}}`
    data := map[string]interface{}{
        "Name":     "Bob",
        "Roles":    []string{"dbteam", "uiteam", "tester"},
    }

    s ,_:= String(tmpl).Format(data)
    fmt.Println(s)
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.