Lorem Ipsum Generator — Go source
Generate placeholder Lorem Ipsum text - paragraphs and sentences with adjustable counts. Classic Latin word pool, instant copy.
This is the Go implementation — the same logic the interactive tool runs, in a shareable, citable form.
// Package loremipsum is the Go twin of CosmoDev's src/lib/lorem.ts (dual source:
// the web lib is TypeScript, the CLI lib is Go — kept in lock-step). Pure in
// shape and never panics; word choice is random via math/rand, mirroring
// Math.random() in the TS lib (lorem generation is inherently random — this is
// the random-twin case, like cli/uuid, not the deterministic case like
// cli/slugify). The table-driven tests in loremipsum_test.go share vectors with
// src/lib/lorem.test.ts so the two implementations are held to the same
// contract.
//
// Algorithm mirrors the TS lib exactly: pick n = minWords + randInt(span)
// words from a fixed pool, join with spaces, capitalize the first character,
// append a period. A paragraph is N such sentences joined by single spaces;
// lorem is M such paragraphs joined by a blank line.
package loremipsum
import (
"math/rand"
"strings"
"unicode"
)
// Words is the canonical lorem-ipsum word pool. It mirrors WORDS in
// src/lib/lorem.ts verbatim (same string, same single-space split). strings.Fields
// is used (rather than a literal split(' ')) so the backtick literal stays
// robust to accidental double spaces, but for this pool it yields the identical
// token list as the TS split(' ').
var Words = strings.Fields(`lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor incididunt ut labore et dolore magna aliqua enim ad minim veniam quis nostrud exercitation ullamco laboris nisi aliquip ex ea commodo consequat duis aute irure in reprehenderit voluptate velit esse cillum eu fugiat nulla pariatur excepteur sint occaecat cupidatat non proident sunt culpa qui officia deserunt mollit anim id est laborum`)
// TS defaults (src/lib/lorem.ts): sentence(minWords=8, maxWords=16),
// paragraph(sentences=5), lorem(paragraphs=3, sentencesPerPara=5). Kept
// unexported so the exported surface mirrors the TS public API exactly; Go
// callers pass explicit values (these constants name the TS defaults).
const (
defaultMinWords = 8
defaultMaxWords = 16
defaultSentences = 5
defaultParagraphs = 3
)
// randInt returns a uniformly random integer in [0, max), mirroring
// randInt(max) = Math.floor(Math.random() * max) in the TS lib. It never
// panics: max <= 0 yields 0. The TS lib only ever calls it with a positive
// bound (WORDS.length, and span — the latter clamped to >= 1), so the guard is
// purely defensive, but a twin must never panic.
func randInt(maxv int) int {
if maxv <= 0 {
return 0
}
return rand.Intn(maxv) // global source; Go 1.20+ auto-seeds it, mirroring Math.random()
}
// Sentence builds a single lorem-ipsum sentence of between minWords and
// maxWords (inclusive) drawn from Words, capitalized and terminated with a
// period. It is the Go twin of sentence(minWords=8, maxWords=16) in
// src/lib/lorem.ts and must agree with it on every shared vector.
//
// Mirrors the TS arithmetic exactly: span = max(1, maxWords-minWords+1),
// n = minWords + randInt(span). Degenerate inputs behave as in TS — e.g.
// Sentence(0, 0) yields n=0 words and so returns just "." (empty join + period);
// a negative resulting word count is clamped to 0, matching TS Array.from's
// treatment of a negative length as empty (and keeping this twin panic-free).
func Sentence(minWords, maxWords int) string {
span := max(maxWords-minWords+1, 1) // mirrors Math.max(1, maxWords-minWords+1)
n := max(minWords+randInt(span), 0) // mirrors Array.from({length: <neg>}) -> []; never panic on make
words := make([]string, n)
for i := range n {
words[i] = Words[randInt(len(Words))]
}
s := strings.Join(words, " ")
if s == "" {
return "." // sentence(0,0) -> "." in TS
}
r := []rune(s)
r[0] = unicode.ToUpper(r[0]) // mirrors s.charAt(0).toUpperCase()
return string(r) + "."
}
// Paragraph builds a paragraph of the given number of default-length sentences
// (8–16 words each) joined by single spaces. It is the Go twin of
// paragraph(sentences=5) in src/lib/lorem.ts. Paragraph(0) returns the empty
// string, matching TS (Array.from({length: 0}).join(' ') === "").
func Paragraph(sentences int) string {
out := make([]string, sentences)
for i := range sentences {
out[i] = Sentence(defaultMinWords, defaultMaxWords)
}
return strings.Join(out, " ")
}
// Lorem builds the requested number of paragraphs (each with sentencesPerPara
// sentences) joined by a blank line ("\n\n"). It is the Go twin of
// lorem(paragraphs=3, sentencesPerPara=5) in src/lib/lorem.ts. Lorem(0, _)
// returns the empty string, matching TS; Lorem(3, 0) returns "\n\n\n\n" (three
// empty paragraphs joined by two "\n\n" separators), again matching TS exactly.
func Lorem(paragraphs, sentencesPerPara int) string {
out := make([]string, paragraphs)
for i := range paragraphs {
out[i] = Paragraph(sentencesPerPara)
}
return strings.Join(out, "\n\n")
}
Also available in 13 other languages
Every CosmoDev tool ships its pure logic in TypeScript (web) and Go (CLI), with authored implementations in a dozen-plus languages — the same contract, ported. Compare all languages side by side →