When you have long text, it might not fit well in a terminal or fixed-width display:
Galaksinin Batı Sarmal Kolu'nun bir ucunda, haritası bile çıkarılmamış ücra bir köşede, gözlerden uzak, küçük ve sarı bir güneş vardır. Bu güneşin yörüngesinde, kabaca yüz kırksekiz milyon kilometre uzağında, tamamıyla önemsiz ve mavi-yeşil renkli, küçük bir gezegen döner.
We want to wrap it to a specific width (e.g., 40 characters):
Galaksinin Batı Sarmal Kolu'nun birucunda, haritası bile çıkarılmamışücra bir köşede, gözlerden uzak,küçük ve sarı bir güneş vardır.Bu güneşin yörüngesinde, kabaca yüzkırksekiz milyon kilometre uzağında,tamamıyla önemsiz ve mavi-yeşilrenkli, küçük bir gezegen döner.
package mainimport ( "fmt" "unicode")func main() { const text = `Galaksinin Batı Sarmal Kolu'nun bir ucunda, haritası bile çıkarılmamış ücra bir köşede, gözlerden uzak, küçük ve sarı bir güneş vardır.Bu güneşin yörüngesinde, kabaca yüz kırksekiz milyon kilometre uzağında, tamamıyla önemsiz ve mavi-yeşil renkli, küçük bir gezegen döner.Gezegenin maymun soyundan gelen canlıları öyle ilkeldir ki dijital kol saatinin hâlâ çok etkileyici bir buluş olduğunu düşünürler.` const maxWidth = 40 var lw int // line width tracker for _, r := range text { fmt.Printf("%c", r) // Increment line width, then check conditions switch lw++; { case lw > maxWidth && r != '\n' && unicode.IsSpace(r): // Line too long and we're at a space (word boundary) fmt.Println() // Start new line fallthrough // Also reset line width case r == '\n': // Original text had a newline lw = 0 // Reset line width counter } } fmt.Println()}
const maxWidth = 40var lw int // line width counter
We track the current line width as we process characters.
2
Iterate Over Runes
for _, r := range text { fmt.Printf("%c", r) // ...}
Using range on a string gives us runes (Unicode code points), not bytes.
This correctly handles multi-byte characters like Turkish “ı”, “ş”, etc.
3
Track Line Width
switch lw++; {case /* conditions */: // ...}
The lw++ in the switch statement increments the counter before evaluating cases.
4
Break at Word Boundaries
case lw > maxWidth && r != '\n' && unicode.IsSpace(r): fmt.Println() // Insert line break fallthrough // Continue to next casecase r == '\n': lw = 0 // Reset counter
Logic:
If line is too long AND we’re at a space (not newline)
text := "Hello 世界" // Mix of ASCII and Unicode// ❌ Iterating over bytes (wrong for Unicode)for i := 0; i < len(text); i++ { fmt.Printf("%c ", text[i]) // Breaks on 世界}// ✅ Iterating over runes (correct)for _, r := range text { fmt.Printf("%c ", r) // Works correctly}
Why? Multi-byte characters like “世” use 3+ bytes. Iterating by byte breaks them.
Switch with Fallthrough
switch x := getValue(); {case x > 10: fmt.Println("Large") fallthrough // Continue to next casecase x > 5: fmt.Println("Medium")default: fmt.Println("Small")}// If x = 15:// Prints "Large" then "Medium"
fallthrough forces execution of the next case, regardless of its condition.
// Word longer than maxWidth"supercalifragilisticexpialidocious" // Will exceed width// Multiple consecutive spaces"hello world" // Breaks at first space// Only whitespace" " // Each space might trigger a break// Empty string"" // Nothing to process
This simple algorithm doesn’t handle words longer than maxWidth. They will overflow the line.
For a production wrapper, you’d need to handle this case (e.g., force-break long words).
# Test with different widthsgo run main.go 20go run main.go 60go run main.go 80# Test with special charactersgo run main.go < turkish_text.txtgo run main.go < emoji_text.txt