Golang中fmt.Sprintf的重要使用方法和注意事项

Golang中fmt.Sprintf的重要使用方法和注意事项 我需要将HTML和CSS转换为单行字符串,这是我的代码:

var buffer bytes.Buffer
buffer.WriteString(fmt.Sprintf("<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'> <html xmlns='http://www.w3.org/1999/xhtml'><head> <meta name='viewport' content='width=device-width, initial-scale=1.0' /> <meta http-equiv='Content-Type' content='text/html; charset=UTF-8' /> <style type='text/css' rel='stylesheet' media='all'> *:not(br):not(tr):not(html) { font-family: Arial, 'Helvetica Neue', Helvetica, sans-serif; -webkit-box-sizing: border-box; box-sizing: border-box; } body { width: 100%% !important; height: 100%; margin: 0; line-height: 1.4; background-color: #F2F4F6; color: #74787E; -webkit-text-size-adjust: none; } a { color: #3869D4; } .email-wrapper { width: 100%%; margin: 0; padding: 0; background-color: #F2F4F6; } .email-content { width: 100%%; margin: 0; padding: 0; } .email-masthead { padding: 25px 0; text-align: center; } .email-masthead_logo { max-width: 400px; border: 0; } .email-masthead_name { font-size: 16px; font-weight: bold; color: #2F3133; text-decoration: none; text-shadow: 0 1px 0 white; } .email-logo { max-height: 50px; } .email-body { width: 100%%; margin: 0; padding: 0; border-top: 1px solid #EDEFF2; border-bottom: 1px solid #EDEFF2; background-color: #FFF; } .email-body_inner { width: 570px; margin: 0 auto; padding: 0; } .email-footer { width: 570px; margin: 0 auto; padding: 0; text-align: center; } .email-footer p { color: #AEAEAE; } .body-action { width: 100%%; margin: 30px auto; padding: 0; text-align: center; } .body-dictionary { width: 100%%; overflow: hidden; margin: 20px auto 10px; padding: 0; } .body-dictionary dd { margin: 0 0 10px 0; } .body-dictionary dt { clear: both; color: #000; font-weight: bold; } .body-dictionary dd { margin-left: 0; margin-bottom: 10px; } .body-sub { margin-top: 25px; padding-top: 25px; border-top: 1px solid #EDEFF2; table-layout: fixed; } .body-sub a { word-break: break-all; } .content-cell { padding: 35px; } .align-right { text-align: right; } h1 { margin-top: 0; color: #2F3133; font-size: 19px; font-weight: bold; } h2 { margin-top: 0; color: #2F3133; font-size: 16px; font-weight: bold; } h3 { margin-top: 0; color: #2F3133; font-size: 14px; font-weight: bold; } blockquote { margin: 1.7rem 0; padding-left: 0.85rem; border-left: 10px solid #F0F2F4; } blockquote p { font-size: 1.1rem; color: #999; } blockquote cite { display: block; text-align: right; color: #666; font-size: 1.2rem; } cite { display: block; font-size: 0.925rem; } cite:before { content: '\2014 \0020'; } p { margin-top: 0; color: #74787E; font-size: 16px; line-height: 1.5em; } p.sub { font-size: 12px; } p.center { text-align: center; } table { width: 100%%; } th { padding: 0px 5px; padding-bottom: 8px; border-bottom: 1px solid #EDEFF2; } th p { margin: 0; color: #9BA2AB; font-size: 12px; } td { padding: 10px 5px; color: #74787E; font-size: 15px; line-height: 18px; } .content { align: center; padding: 0; } .data-wrapper { width: 100%%; margin: 0; padding: 35px 0; } .data-table { width: 100%%; margin: 0; } .data-table th { text-align: left; padding: 0px 5px; padding-bottom: 8px; border-bottom: 1px solid #EDEFF2; } .data-table th p { margin: 0; color: #9BA2AB; font-size: 12px; } .data-table td { padding: 10px 5px; color: #74787E; font-size: 15px; line-height: 18px; } .button { display: inline-block; width: 200px; background-color: #3869D4; border-radius: 3px; color: #ffffff; font-size: 15px; line-height: 45px; text-align: center; text-decoration: none; -webkit-text-size-adjust: none; mso-hide: all; } @media only screen and (max-width: 600px) { .email-body_inner, .email-footer { width: 100%% !important; } } @media only screen and (max-width: 500px) { .button { width: 100%% !important; } } </style> </head><body dir='ltr'> <table class='email-wrapper' width='100%%' cellpadding='0' cellspacing='0'> <tr> <td class='content'> <table class='email-content' width='100%%' cellpadding='0' cellspacing='0'><tr> <td class='email-masthead'> <a class='email-masthead_name' href='https://example-hermes.com/' target='_blank'><img src='https://unie-assets.ams3.digitaloceanspaces.com/images/logo-unie.png' class='email-logo' /></a> </td> </tr><tr> <td class='email-body' width='100%%'> <table class='email-body_inner' align='center' width='570' cellpadding='0' cellspacing='0'>"))

它返回了一个无效的字符串,我在CSS中发现了一个错误:

 .button {
            width: 100% !important;
 }

在输出中它看起来像这样:

    .button { width: 100% !!(MISSING)important;}

更多关于Golang中fmt.Sprintf的重要使用方法和注意事项的实战教程也可以访问 https://www.itying.com/category-94-b0.html

4 回复

为什么你在那里使用 fmt.Sprintf?看起来你除了字符串之外没有提供其他参数。

更多关于Golang中fmt.Sprintf的重要使用方法和注意事项的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


顺便说一句,从你最近创建的主题来看,或许你应该看看 html/template 包:https://golang.org/pkg/html/template/

这是处理HTML和你正在尝试做的事情的更好方式!

你好

你之后肯定对缓冲区进行了其他操作,因为你提供的这段代码片段运行正常,并没有产生"缺失"的字符串

https://goplay.space/#vHW5dD7Z8wB

在使用fmt.Sprintf格式化包含百分比符号的字符串时,需要特别注意转义处理。在你的CSS代码中,width: 100% !important;中的%符号被fmt.Sprintf误认为是格式化占位符,导致输出异常。

问题分析

fmt.Sprintf%符号解析为格式化动词的开始,当遇到% !时,它期望后面跟着有效的格式化指令,但!important不是有效的格式化语法,因此产生了!!(MISSING)的错误输出。

解决方案

1. 转义百分比符号

将CSS中的所有%符号替换为%%进行转义:

htmlContent := fmt.Sprintf(`<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'> 
<html xmlns='http://www.w3.org/1999/xhtml'>
<head>
<meta name='viewport' content='width=device-width, initial-scale=1.0' />
<meta http-equiv='Content-Type' content='text/html; charset=UTF-8' />
<style type='text/css' rel='stylesheet' media='all'>
body {
    width: 100%% !important;
    height: 100%%;
    margin: 0;
    line-height: 1.4;
    background-color: #F2F4F6;
    color: #74787E;
    -webkit-text-size-adjust: none;
}
.email-wrapper {
    width: 100%%;
    margin: 0;
    padding: 0;
    background-color: #F2F4F6;
}
.button {
    width: 100%% !important;
}
@media only screen and (max-width: 600px) {
    .email-body_inner, .email-footer {
        width: 100%% !important;
    }
}
</style>
</head>
<body dir='ltr'>
<table class='email-wrapper' width='100%%' cellpadding='0' cellspacing='0'>
<tr>
<td class='content'>
<table class='email-content' width='100%%' cellpadding='0' cellspacing='0'>
</table>
</td>
</tr>
</table>
</body>
</html>`)

2. 使用原始字符串字面量

对于包含大量特殊字符的HTML/CSS内容,使用反引号定义原始字符串更安全:

htmlTemplate := `<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'>
<html xmlns='http://www.w3.org/1999/xhtml'>
<head>
<style type='text/css' rel='stylesheet' media='all'>
body { width: 100% !important; height: 100%; }
.button { width: 100% !important; }
</style>
</head>
<body>%s</body>
</html>`

// 当需要插入动态内容时再使用Sprintf
dynamicContent := "<div>Hello World</div>"
finalHTML := fmt.Sprintf(htmlTemplate, dynamicContent)

3. 使用strings.Builder替代bytes.Buffer

对于字符串拼接,strings.Builder通常更高效:

var builder strings.Builder
builder.WriteString("<!DOCTYPE html>")
builder.WriteString("<html>")
builder.WriteString("<style>")
builder.WriteString("body { width: 100% !important; }") // 这里不需要转义
builder.WriteString("</style>")
builder.WriteString("</html>")
result := builder.String()

重要注意事项

  1. 转义规则:在fmt.Sprintf中,%需要转义为%%\需要转义为\\

  2. 性能考虑:对于大量字符串拼接,strings.Builderfmt.Sprintf更高效

  3. 可读性:对于复杂的HTML模板,考虑使用html/template包:

import "html/template"

const emailTemplate = `
<!DOCTYPE html>
<html>
<head>
<style>
.button { width: {{.ButtonWidth}} !important; }
</style>
</head>
<body>
<div class="button">Click me</div>
</body>
</html>`

tmpl, err := template.New("email").Parse(emailTemplate)
if err != nil {
    panic(err)
}

var buf bytes.Buffer
data := struct {
    ButtonWidth string
}{
    ButtonWidth: "100%",
}
tmpl.Execute(&buf, data)
result := buf.String()

通过正确处理百分比符号的转义,你的CSS代码将正确输出为单行字符串。

回到顶部